summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkelvinp <kelvinp@chromium.org>2014-10-07 14:49:39 -0700
committerCommit bot <commit-bot@chromium.org>2014-10-07 21:50:09 +0000
commit3b73f509613829b8b0719ee739292228a83c00ac (patch)
treecdfe05d42e75e712d41e911b80671e831c12169e
parentd57fab48d959e58fc0b1e643eed05be7927b2318 (diff)
downloadchromium_src-3b73f509613829b8b0719ee739292228a83c00ac.zip
chromium_src-3b73f509613829b8b0719ee739292228a83c00ac.tar.gz
chromium_src-3b73f509613829b8b0719ee739292228a83c00ac.tar.bz2
Remote Assistance on Chrome OS Part III - NativeMessageHost
This CL extracts the NativeMessageHost interface from the NativeMessageProcessHost A NativeMessageHost hosts a native component, which can be running in the same process as chrome or in a separate process. Committed: https://crrev.com/ba722a2a8ddf967dcadb483ea32d5ad31fc4bdf6 Cr-Commit-Position: refs/heads/master@{#298366} Review URL: https://codereview.chromium.org/591463003 Cr-Commit-Position: refs/heads/master@{#298579}
-rw-r--r--chrome/app/generated_resources.grd6
-rw-r--r--chrome/browser/about_flags.cc10
-rw-r--r--chrome/browser/extensions/api/messaging/message_service.cc72
-rw-r--r--chrome/browser/extensions/api/messaging/message_service.h23
-rw-r--r--chrome/browser/extensions/api/messaging/native_message_host_chromeos.cc155
-rw-r--r--chrome/browser/extensions/api/messaging/native_message_port.cc109
-rw-r--r--chrome/browser/extensions/api/messaging/native_message_port.h22
-rw-r--r--chrome/browser/extensions/api/messaging/native_message_process_host.cc137
-rw-r--r--chrome/browser/extensions/api/messaging/native_message_process_host.h63
-rw-r--r--chrome/browser/extensions/api/messaging/native_message_process_host_unittest.cc92
-rw-r--r--chrome/browser/policy/policy_browsertest.cc14
-rw-r--r--chrome/chrome_browser_extensions.gypi13
-rw-r--r--chrome/test/data/extensions/api_test/native_messaging/test.js7
-rw-r--r--extensions/browser/BUILD.gn1
-rw-r--r--extensions/browser/api/messaging/native_message_host.cc21
-rw-r--r--extensions/browser/api/messaging/native_message_host.h62
-rw-r--r--extensions/common/switches.cc4
-rw-r--r--extensions/common/switches.h1
-rw-r--r--extensions/extensions.gyp1
-rw-r--r--remoting/host/it2me/com.google.chrome.remote_assistance.json.jinja23
-rw-r--r--remoting/host/it2me/it2me_native_messaging_host.cc60
-rw-r--r--remoting/host/it2me/it2me_native_messaging_host.h39
-rw-r--r--remoting/host/it2me/it2me_native_messaging_host_main.cc15
-rw-r--r--remoting/host/it2me/it2me_native_messaging_host_unittest.cc33
-rw-r--r--remoting/host/native_messaging/native_messaging_pipe.cc52
-rw-r--r--remoting/host/native_messaging/native_messaging_pipe.h50
-rw-r--r--remoting/remoting_host.gypi2
-rw-r--r--tools/metrics/histograms/histograms.xml1
28 files changed, 759 insertions, 309 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 4fe90bd..4603928 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -13863,6 +13863,12 @@ Do you accept?
<message name="IDS_FLAGS_ENABLE_EXPERIMENTAL_INPUT_VIEW_FEATURES_DESCRIPTION" desc="Description of about::flags option to enable experimental features for IME input-views">
Enable experimental features for IME input views.
</message>
+ <message name="IDS_FLAGS_ENABLE_REMOTE_ASSISTANCE_NAME" desc="Name of about::flags option to enable remote assistance on Chrome OS">
+ Enable Remote Assistance
+ </message>
+ <message name="IDS_FLAGS_ENABLE_REMOTE_ASSISTANCE_DESCRIPTION" desc="Description of about::flags option to enable remote assistance on Chrome OS.">
+ Accepts remote assistance connections to this machine via the Chrome Remote Desktop app.
+ </message>
</if>
<!-- Simple Cache Backend experiment. -->
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 4549449..413ff41 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1961,7 +1961,15 @@ const Experiment kExperiments[] = {
SINGLE_VALUE_TYPE(switches::kEnablePluginPowerSaver)
},
#endif
-
+#if defined(OS_CHROMEOS)
+ {
+ "enable-remote-assistance",
+ IDS_FLAGS_ENABLE_REMOTE_ASSISTANCE_NAME,
+ IDS_FLAGS_ENABLE_REMOTE_ASSISTANCE_DESCRIPTION,
+ kOsCrOS,
+ SINGLE_VALUE_TYPE(extensions::switches::kEnableRemoteAssistance)
+ },
+#endif // defined(OS_CHROMEOS)
// NOTE: Adding new command-line switches requires adding corresponding
// entries to enum "LoginCustomFlags" in histograms.xml. See note in
// histograms.xml and don't forget to run AboutFlagsHistogramTest unit test.
diff --git a/chrome/browser/extensions/api/messaging/message_service.cc b/chrome/browser/extensions/api/messaging/message_service.cc
index b648089..fb72711 100644
--- a/chrome/browser/extensions/api/messaging/message_service.cc
+++ b/chrome/browser/extensions/api/messaging/message_service.cc
@@ -10,6 +10,7 @@
#include "base/json/json_writer.h"
#include "base/lazy_instance.h"
#include "base/metrics/histogram.h"
+#include "base/prefs/pref_service.h"
#include "base/stl_util.h"
#include "base/values.h"
#include "chrome/browser/chrome_notification_types.h"
@@ -33,6 +34,7 @@
#include "extensions/browser/extension_system.h"
#include "extensions/browser/extensions_browser_client.h"
#include "extensions/browser/lazy_background_task_queue.h"
+#include "extensions/browser/pref_names.h"
#include "extensions/browser/process_manager.h"
#include "extensions/common/extension.h"
#include "extensions/common/manifest_constants.h"
@@ -61,6 +63,44 @@ using content::WebContents;
namespace extensions {
+MessageService::PolicyPermission MessageService::IsNativeMessagingHostAllowed(
+ const PrefService* pref_service,
+ const std::string& native_host_name) {
+ PolicyPermission allow_result = ALLOW_ALL;
+ if (pref_service->IsManagedPreference(
+ pref_names::kNativeMessagingUserLevelHosts)) {
+ if (!pref_service->GetBoolean(pref_names::kNativeMessagingUserLevelHosts))
+ allow_result = ALLOW_SYSTEM_ONLY;
+ }
+
+ // All native messaging hosts are allowed if there is no blacklist.
+ if (!pref_service->IsManagedPreference(pref_names::kNativeMessagingBlacklist))
+ return allow_result;
+ const base::ListValue* blacklist =
+ pref_service->GetList(pref_names::kNativeMessagingBlacklist);
+ if (!blacklist)
+ return allow_result;
+
+ // Check if the name or the wildcard is in the blacklist.
+ base::StringValue name_value(native_host_name);
+ base::StringValue wildcard_value("*");
+ if (blacklist->Find(name_value) == blacklist->end() &&
+ blacklist->Find(wildcard_value) == blacklist->end()) {
+ return allow_result;
+ }
+
+ // The native messaging host is blacklisted. Check the whitelist.
+ if (pref_service->IsManagedPreference(
+ pref_names::kNativeMessagingWhitelist)) {
+ const base::ListValue* whitelist =
+ pref_service->GetList(pref_names::kNativeMessagingWhitelist);
+ if (whitelist && whitelist->Find(name_value) != whitelist->end())
+ return allow_result;
+ }
+
+ return DISALLOW;
+}
+
const char kReceivingEndDoesntExistError[] =
"Could not establish connection. Receiving end does not exist.";
#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
@@ -371,9 +411,9 @@ void MessageService::OpenChannelToNativeApp(
PrefService* pref_service = profile->GetPrefs();
// Verify that the host is not blocked by policies.
- NativeMessageProcessHost::PolicyPermission policy_permission =
- NativeMessageProcessHost::IsHostAllowed(pref_service, native_app_name);
- if (policy_permission == NativeMessageProcessHost::DISALLOW) {
+ PolicyPermission policy_permission =
+ IsNativeMessagingHostAllowed(pref_service, native_app_name);
+ if (policy_permission == DISALLOW) {
DispatchOnDisconnect(source, receiver_port_id, kProhibitedByPoliciesError);
return;
}
@@ -387,22 +427,23 @@ void MessageService::OpenChannelToNativeApp(
content::RenderWidgetHost::FromID(source_process_id, source_routing_id)->
GetView()->GetNativeView();
- scoped_ptr<NativeMessageProcessHost> native_process =
- NativeMessageProcessHost::Create(
- native_view,
- base::WeakPtr<NativeMessageProcessHost::Client>(
- weak_factory_.GetWeakPtr()),
- source_extension_id, native_app_name, receiver_port_id,
- policy_permission == NativeMessageProcessHost::ALLOW_ALL);
+ std::string error = kReceivingEndDoesntExistError;
+ scoped_ptr<NativeMessageHost> native_host = NativeMessageHost::Create(
+ native_view,
+ source_extension_id,
+ native_app_name,
+ policy_permission == ALLOW_ALL,
+ &error);
// Abandon the channel.
- if (!native_process.get()) {
+ if (!native_host.get()) {
LOG(ERROR) << "Failed to create native process.";
DispatchOnDisconnect(
- source, receiver_port_id, kReceivingEndDoesntExistError);
+ source, receiver_port_id, error);
return;
}
- channel->receiver.reset(new NativeMessagePort(native_process.release()));
+ channel->receiver.reset(new NativeMessagePort(
+ weak_factory_.GetWeakPtr(), receiver_port_id, native_host.Pass()));
// Keep the opener alive until the channel is closed.
channel->opener->IncrementLazyKeepaliveCount();
@@ -562,11 +603,6 @@ void MessageService::PostMessage(int source_port_id, const Message& message) {
DispatchMessage(source_port_id, iter->second, message);
}
-void MessageService::PostMessageFromNativeProcess(int port_id,
- const std::string& message) {
- PostMessage(port_id, Message(message, false /* user_gesture */));
-}
-
void MessageService::Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
diff --git a/chrome/browser/extensions/api/messaging/message_service.h b/chrome/browser/extensions/api/messaging/message_service.h
index 2fc5e80..23bf7e8 100644
--- a/chrome/browser/extensions/api/messaging/message_service.h
+++ b/chrome/browser/extensions/api/messaging/message_service.h
@@ -14,9 +14,9 @@
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/extensions/api/messaging/message_property_provider.h"
-#include "chrome/browser/extensions/api/messaging/native_message_process_host.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
+#include "extensions/browser/api/messaging/native_message_host.h"
#include "extensions/browser/browser_context_keyed_api_factory.h"
#include "extensions/common/api/messaging/message.h"
@@ -60,8 +60,7 @@ class LazyBackgroundTaskQueue;
// case that the port is a tab). The Process is usually either a
// RenderProcessHost or a RenderViewHost.
class MessageService : public BrowserContextKeyedAPI,
- public content::NotificationObserver,
- public NativeMessageProcessHost::Client {
+ public content::NotificationObserver {
public:
// A messaging channel. Note that the opening port can be the same as the
// receiver, if an extension background page wants to talk to its tab (for
@@ -105,6 +104,16 @@ class MessageService : public BrowserContextKeyedAPI,
DISALLOW_COPY_AND_ASSIGN(MessagePort);
};
+ enum PolicyPermission {
+ DISALLOW, // The host is not allowed.
+ ALLOW_SYSTEM_ONLY, // Allowed only when installed on system level.
+ ALLOW_ALL, // Allowed when installed on system or user level.
+ };
+
+ static PolicyPermission IsNativeMessagingHostAllowed(
+ const PrefService* pref_service,
+ const std::string& native_host_name);
+
// Allocates a pair of port ids.
// NOTE: this can be called from any thread.
static void AllocatePortIdPair(int* port1, int* port2);
@@ -146,18 +155,12 @@ class MessageService : public BrowserContextKeyedAPI,
// Closes the message channel associated with the given port, and notifies
// the other side.
- virtual void CloseChannel(int port_id,
- const std::string& error_message) override;
+ void CloseChannel(int port_id, const std::string& error_message);
// Enqueues a message on a pending channel, or sends a message to the given
// port if the channel isn't pending.
void PostMessage(int port_id, const Message& message);
- // NativeMessageProcessHost::Client
- virtual void PostMessageFromNativeProcess(
- int port_id,
- const std::string& message) override;
-
private:
friend class MockMessageService;
friend class BrowserContextKeyedAPIFactory<MessageService>;
diff --git a/chrome/browser/extensions/api/messaging/native_message_host_chromeos.cc b/chrome/browser/extensions/api/messaging/native_message_host_chromeos.cc
new file mode 100644
index 0000000..e42b014
--- /dev/null
+++ b/chrome/browser/extensions/api/messaging/native_message_host_chromeos.cc
@@ -0,0 +1,155 @@
+// Copyright 2014 The Chromium 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 "extensions/browser/api/messaging/native_message_host.h"
+
+#include <string>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/command_line.h"
+#include "base/json/json_reader.h"
+#include "base/json/json_writer.h"
+#include "base/location.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/values.h"
+#include "chrome/browser/extensions/api/messaging/native_messaging_test_util.h"
+#include "extensions/common/constants.h"
+#include "extensions/common/url_pattern.h"
+#include "ui/gfx/native_widget_types.h"
+#include "url/gurl.h"
+
+namespace extensions {
+
+namespace {
+
+// A simple NativeMesageHost that echoes the received message. It is currently
+// used for testing.
+// TODO(kelvinp): Replace this class once Remote Assistance in process host
+// is implemented.
+
+const char* const kEchoHostOrigins[] = {
+ // ScopedTestNativeMessagingHost::kExtensionId
+ "chrome-extension://knldjmfmopnpolahpmmgbagdohdnhkik/"};
+
+class EchoHost : public NativeMessageHost {
+ public:
+ static scoped_ptr<NativeMessageHost> Create() {
+ return scoped_ptr<NativeMessageHost>(new EchoHost());
+ }
+
+ EchoHost() : message_number_(0), client_(NULL) {}
+
+ virtual void Start(Client* client) OVERRIDE {
+ client_ = client;
+ }
+
+ virtual void OnMessage(const std::string& request_string) OVERRIDE {
+ scoped_ptr<base::Value> request_value(
+ base::JSONReader::Read(request_string));
+ scoped_ptr<base::DictionaryValue> request(
+ static_cast<base::DictionaryValue*>(request_value.release()));
+ if (request_string.find("stopHostTest") != std::string::npos) {
+ client_->CloseChannel(kNativeHostExited);
+ } else if (request_string.find("bigMessageTest") != std::string::npos) {
+ client_->CloseChannel(kHostInputOuputError);
+ } else {
+ ProcessEcho(*request);
+ }
+ };
+
+ virtual scoped_refptr<base::SingleThreadTaskRunner> task_runner()
+ const OVERRIDE {
+ return base::MessageLoopProxy::current();
+ };
+
+ private:
+ void ProcessEcho(const base::DictionaryValue& request) {
+ scoped_ptr<base::DictionaryValue> response(new base::DictionaryValue());
+ response->SetInteger("id", ++message_number_);
+ response->Set("echo", request.DeepCopy());
+ response->SetString("caller_url", kEchoHostOrigins[0]);
+ std::string response_string;
+ base::JSONWriter::Write(response.get(), &response_string);
+ client_->PostMessageFromNativeHost(response_string);
+ }
+
+ int message_number_;
+ Client* client_;
+
+ DISALLOW_COPY_AND_ASSIGN(EchoHost);
+};
+
+struct BuiltInHost {
+ const char* const name;
+ const char* const* const allowed_origins;
+ int allowed_origins_count;
+ scoped_ptr<NativeMessageHost>(*create_function)();
+};
+
+// If you modify the list of allowed_origins, don't forget to update
+// remoting/host/it2me/com.google.chrome.remote_assistance.json.jinja2
+// to keep the two lists in sync.
+// TODO(kelvinp): Load the native messaging manifest as a resource file into
+// chrome and fetch the list of allowed_origins from the manifest.
+/*const char* const kRemotingIt2MeOrigins[] = {
+ "chrome-extension://ljacajndfccfgnfohlgkdphmbnpkjflk/",
+ "chrome-extension://gbchcmhmhahfdphkhkmpfmihenigjmpp/",
+ "chrome-extension://kgngmbheleoaphbjbaiobfdepmghbfah/",
+ "chrome-extension://odkaodonbgfohohmklejpjiejmcipmib/",
+ "chrome-extension://dokpleeekgeeiehdhmdkeimnkmoifgdd/",
+ "chrome-extension://ajoainacpilcemgiakehflpbkbfipojk/",
+ "chrome-extension://hmboipgjngjoiaeicfdifdoeacilalgc/"};*/
+
+static const BuiltInHost kBuiltInHost[] = {
+ {"com.google.chrome.test.echo", // ScopedTestNativeMessagingHost::kHostName
+ kEchoHostOrigins,
+ arraysize(kEchoHostOrigins),
+ &EchoHost::Create},
+};
+
+bool MatchesSecurityOrigin(const BuiltInHost& host,
+ const std::string& extension_id) {
+ GURL origin(std::string(kExtensionScheme) + "://" + extension_id);
+ for (int i = 0; i < host.allowed_origins_count; i++) {
+ URLPattern allowed_origin(URLPattern::SCHEME_ALL);
+ DCHECK_EQ(URLPattern::PARSE_SUCCESS,
+ allowed_origin.Parse(host.allowed_origins[i]));
+ LOG(ERROR) << "allowed_origin is " << allowed_origin.GetAsString()
+ << " and extension_id is " << extension_id;
+ if (allowed_origin.MatchesSecurityOrigin(origin)) {
+ LOG(ERROR) << "Pattern matched";
+ return true;
+ }
+ }
+ LOG(ERROR) << "Pattern mismatched";
+ return false;
+}
+
+} // namespace
+
+scoped_ptr<NativeMessageHost> NativeMessageHost::Create(
+ gfx::NativeView native_view,
+ const std::string& source_extension_id,
+ const std::string& native_host_name,
+ bool allow_user_level,
+ std::string* error) {
+ for (unsigned int i = 0; i < arraysize(kBuiltInHost); i++) {
+ const BuiltInHost& host = kBuiltInHost[i];
+ std::string name(host.name);
+ if (name == native_host_name) {
+ if (MatchesSecurityOrigin(host, source_extension_id)) {
+ return (*host.create_function)();
+ }
+ *error = kForbiddenError;
+ return nullptr;
+ }
+ }
+ *error = kNotFoundError;
+ return nullptr;
+}
+
+} // namespace extensions
diff --git a/chrome/browser/extensions/api/messaging/native_message_port.cc b/chrome/browser/extensions/api/messaging/native_message_port.cc
index a0a47d5..66b1674 100644
--- a/chrome/browser/extensions/api/messaging/native_message_port.cc
+++ b/chrome/browser/extensions/api/messaging/native_message_port.cc
@@ -5,27 +5,120 @@
#include "chrome/browser/extensions/api/messaging/native_message_port.h"
#include "base/bind.h"
+#include "base/single_thread_task_runner.h"
#include "chrome/browser/extensions/api/messaging/native_message_process_host.h"
#include "content/public/browser/browser_thread.h"
namespace extensions {
-NativeMessagePort::NativeMessagePort(NativeMessageProcessHost* native_process)
- : native_process_(native_process) {
+// Handles jumping between the |host_task_runner| and the
+// |message_service_task_runner|.
+// All methods on the host interface should be called on |host_task_runner|.
+// All methods on |port| (that calls into MessageServices) should be called
+// on |message_service_task_runner|.
+class NativeMessagePort::Core : public NativeMessageHost::Client {
+ public:
+ Core(
+ scoped_ptr<NativeMessageHost> host,
+ base::WeakPtr<NativeMessagePort> port,
+ scoped_refptr<base::SingleThreadTaskRunner> message_service_task_runner_);
+ virtual ~Core();
+
+ void OnMessageFromChrome(const std::string& message);
+
+ // NativeMessageHost::Client implementation.
+ virtual void PostMessageFromNativeHost(const std::string& message) OVERRIDE;
+ virtual void CloseChannel(const std::string& error_message) OVERRIDE;
+
+ private:
+ scoped_ptr<NativeMessageHost> host_;
+ base::WeakPtr<NativeMessagePort> port_;
+
+ scoped_refptr<base::SingleThreadTaskRunner> message_service_task_runner_;
+ scoped_refptr<base::SingleThreadTaskRunner> host_task_runner_;
+};
+
+NativeMessagePort::Core::Core(
+ scoped_ptr<NativeMessageHost> host,
+ base::WeakPtr<NativeMessagePort> port,
+ scoped_refptr<base::SingleThreadTaskRunner> message_service_task_runner)
+ : host_(host.Pass()),
+ port_(port),
+ message_service_task_runner_(message_service_task_runner),
+ host_task_runner_(host_->task_runner()) {
+ DCHECK(message_service_task_runner_->BelongsToCurrentThread());
+ host_task_runner_->PostTask(FROM_HERE,
+ base::Bind(&NativeMessageHost::Start,
+ base::Unretained(host_.get()),
+ base::Unretained(this)));
+}
+
+NativeMessagePort::Core::~Core() {
+ DCHECK(host_task_runner_->BelongsToCurrentThread());
+}
+
+void NativeMessagePort::Core::OnMessageFromChrome(const std::string& message) {
+ DCHECK(message_service_task_runner_->BelongsToCurrentThread());
+ host_task_runner_->PostTask(FROM_HERE,
+ base::Bind(&NativeMessageHost::OnMessage,
+ base::Unretained(host_.get()),
+ message));
+}
+
+void NativeMessagePort::Core::PostMessageFromNativeHost(
+ const std::string& message) {
+ DCHECK(host_task_runner_->BelongsToCurrentThread());
+ message_service_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &NativeMessagePort::PostMessageFromNativeHost, port_, message));
+}
+
+void NativeMessagePort::Core::CloseChannel(const std::string& error_message) {
+ DCHECK(host_task_runner_->BelongsToCurrentThread());
+ message_service_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&NativeMessagePort::CloseChannel, port_, error_message));
+}
+
+NativeMessagePort::NativeMessagePort(
+ base::WeakPtr<MessageService> message_service,
+ int port_id,
+ scoped_ptr<NativeMessageHost> native_message_host)
+ : weak_message_service_(message_service),
+ host_task_runner_(native_message_host->task_runner()),
+ port_id_(port_id),
+ weak_factory_(this) {
+ core_.reset(new Core(native_message_host.Pass(),
+ weak_factory_.GetWeakPtr(),
+ base::MessageLoopProxy::current()));
}
NativeMessagePort::~NativeMessagePort() {
- content::BrowserThread::DeleteSoon(
- content::BrowserThread::IO, FROM_HERE, native_process_);
+ DCHECK(thread_checker_.CalledOnValidThread());
+ host_task_runner_->DeleteSoon(FROM_HERE, core_.release());
}
void NativeMessagePort::DispatchOnMessage(
const Message& message,
int target_port_id) {
- content::BrowserThread::PostTask(
- content::BrowserThread::IO, FROM_HERE,
- base::Bind(&NativeMessageProcessHost::Send,
- base::Unretained(native_process_), message.data));
+ DCHECK(thread_checker_.CalledOnValidThread());
+ core_->OnMessageFromChrome(message.data);
+}
+
+void NativeMessagePort::PostMessageFromNativeHost(const std::string& message) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (weak_message_service_) {
+ weak_message_service_->PostMessage(
+ port_id_, Message(message, false /* user_gesture */));
+ }
+}
+
+void NativeMessagePort::CloseChannel(const std::string& error_message) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (weak_message_service_) {
+ weak_message_service_->CloseChannel(port_id_, error_message);
+ }
}
} // namespace extensions
diff --git a/chrome/browser/extensions/api/messaging/native_message_port.h b/chrome/browser/extensions/api/messaging/native_message_port.h
index b3f7605..65711ae 100644
--- a/chrome/browser/extensions/api/messaging/native_message_port.h
+++ b/chrome/browser/extensions/api/messaging/native_message_port.h
@@ -5,22 +5,36 @@
#ifndef CHROME_BROWSER_EXTENSIONS_API_MESSAGING_NATIVE_MESSAGE_PORT_H_
#define CHROME_BROWSER_EXTENSIONS_API_MESSAGING_NATIVE_MESSAGE_PORT_H_
+#include "base/threading/thread_checker.h"
#include "chrome/browser/extensions/api/messaging/message_service.h"
namespace extensions {
class NativeMessageProcessHost;
// A port that manages communication with a native application.
+// All methods must be called on the UI Thread of the browser process.
class NativeMessagePort : public MessageService::MessagePort {
public:
- // Takes ownership of |native_process|.
- explicit NativeMessagePort(NativeMessageProcessHost* native_process);
+ NativeMessagePort(base::WeakPtr<MessageService> message_service,
+ int port_id,
+ scoped_ptr<NativeMessageHost> native_message_host);
virtual ~NativeMessagePort();
+
+ // MessageService::MessagePort implementation.
virtual void DispatchOnMessage(const Message& message,
int target_port_id) override;
-
private:
- NativeMessageProcessHost* native_process_;
+ class Core;
+ void PostMessageFromNativeHost(const std::string& message);
+ void CloseChannel(const std::string& error_message);
+
+ base::ThreadChecker thread_checker_;
+ base::WeakPtr<MessageService> weak_message_service_;
+ scoped_refptr<base::SingleThreadTaskRunner> host_task_runner_;
+ int port_id_;
+ scoped_ptr<Core> core_;
+
+ base::WeakPtrFactory<NativeMessagePort> weak_factory_;
};
} // namespace extensions
diff --git a/chrome/browser/extensions/api/messaging/native_message_process_host.cc b/chrome/browser/extensions/api/messaging/native_message_process_host.cc
index 7d7e37f..bc3808a 100644
--- a/chrome/browser/extensions/api/messaging/native_message_process_host.cc
+++ b/chrome/browser/extensions/api/messaging/native_message_process_host.cc
@@ -7,15 +7,12 @@
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/logging.h"
-#include "base/prefs/pref_service.h"
#include "base/process/kill.h"
#include "base/threading/sequenced_worker_pool.h"
-#include "base/values.h"
#include "chrome/browser/extensions/api/messaging/native_messaging_host_manifest.h"
#include "chrome/browser/extensions/api/messaging/native_process_launcher.h"
#include "chrome/common/chrome_version_info.h"
#include "content/public/browser/browser_thread.h"
-#include "extensions/browser/pref_names.h"
#include "extensions/common/constants.h"
#include "extensions/common/features/feature.h"
#include "net/base/file_stream.h"
@@ -37,69 +34,16 @@ const size_t kMessageHeaderSize = 4;
// Size of the buffer to be allocated for each read.
const size_t kReadBufferSize = 4096;
-const char kFailedToStartError[] = "Failed to start native messaging host.";
-const char kInvalidNameError[] =
- "Invalid native messaging host name specified.";
-const char kNativeHostExited[] = "Native host has exited.";
-const char kNotFoundError[] = "Specified native messaging host not found.";
-const char kForbiddenError[] =
- "Access to the specified native messaging host is forbidden.";
-const char kHostInputOuputError[] =
- "Error when communicating with the native messaging host.";
-
} // namespace
namespace extensions {
-// static
-NativeMessageProcessHost::PolicyPermission
-NativeMessageProcessHost::IsHostAllowed(const PrefService* pref_service,
- const std::string& native_host_name) {
- NativeMessageProcessHost::PolicyPermission allow_result = ALLOW_ALL;
- if (pref_service->IsManagedPreference(
- pref_names::kNativeMessagingUserLevelHosts)) {
- if (!pref_service->GetBoolean(pref_names::kNativeMessagingUserLevelHosts))
- allow_result = ALLOW_SYSTEM_ONLY;
- }
-
- // All native messaging hosts are allowed if there is no blacklist.
- if (!pref_service->IsManagedPreference(pref_names::kNativeMessagingBlacklist))
- return allow_result;
- const base::ListValue* blacklist =
- pref_service->GetList(pref_names::kNativeMessagingBlacklist);
- if (!blacklist)
- return allow_result;
-
- // Check if the name or the wildcard is in the blacklist.
- base::StringValue name_value(native_host_name);
- base::StringValue wildcard_value("*");
- if (blacklist->Find(name_value) == blacklist->end() &&
- blacklist->Find(wildcard_value) == blacklist->end()) {
- return allow_result;
- }
-
- // The native messaging host is blacklisted. Check the whitelist.
- if (pref_service->IsManagedPreference(
- pref_names::kNativeMessagingWhitelist)) {
- const base::ListValue* whitelist =
- pref_service->GetList(pref_names::kNativeMessagingWhitelist);
- if (whitelist && whitelist->Find(name_value) != whitelist->end())
- return allow_result;
- }
-
- return DISALLOW;
-}
-
NativeMessageProcessHost::NativeMessageProcessHost(
- base::WeakPtr<Client> weak_client_ui,
const std::string& source_extension_id,
const std::string& native_host_name,
- int destination_port,
scoped_ptr<NativeProcessLauncher> launcher)
- : weak_client_ui_(weak_client_ui),
- source_extension_id_(source_extension_id),
+ : source_extension_id_(source_extension_id),
native_host_name_(native_host_name),
- destination_port_(destination_port),
launcher_(launcher.Pass()),
closed_(false),
process_handle_(base::kNullProcessHandle),
@@ -110,51 +54,50 @@ NativeMessageProcessHost::NativeMessageProcessHost(
write_pending_(false) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ task_runner_ = content::BrowserThread::GetMessageLoopProxyForThread(
+ content::BrowserThread::IO);
// It's safe to use base::Unretained() here because NativeMessagePort always
// deletes us on the IO thread.
- content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
+ task_runner_->PostTask(
+ FROM_HERE,
base::Bind(&NativeMessageProcessHost::LaunchHostProcess,
base::Unretained(this)));
}
NativeMessageProcessHost::~NativeMessageProcessHost() {
- DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
- Close(std::string());
+ DCHECK(task_runner_->BelongsToCurrentThread());
}
// static
-scoped_ptr<NativeMessageProcessHost> NativeMessageProcessHost::Create(
+scoped_ptr<NativeMessageHost> NativeMessageHost::Create(
gfx::NativeView native_view,
- base::WeakPtr<Client> weak_client_ui,
const std::string& source_extension_id,
const std::string& native_host_name,
- int destination_port,
- bool allow_user_level) {
- return CreateWithLauncher(weak_client_ui, source_extension_id,
- native_host_name, destination_port,
- NativeProcessLauncher::CreateDefault(
- allow_user_level, native_view));
+ bool allow_user_level,
+ std::string* error_message) {
+ return NativeMessageProcessHost::CreateWithLauncher(
+ source_extension_id,
+ native_host_name,
+ NativeProcessLauncher::CreateDefault(allow_user_level, native_view));
}
// static
-scoped_ptr<NativeMessageProcessHost>
-NativeMessageProcessHost::CreateWithLauncher(
- base::WeakPtr<Client> weak_client_ui,
+scoped_ptr<NativeMessageHost> NativeMessageProcessHost::CreateWithLauncher(
const std::string& source_extension_id,
const std::string& native_host_name,
- int destination_port,
scoped_ptr<NativeProcessLauncher> launcher) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- scoped_ptr<NativeMessageProcessHost> process(new NativeMessageProcessHost(
- weak_client_ui, source_extension_id, native_host_name,
- destination_port, launcher.Pass()));
+ scoped_ptr<NativeMessageHost> process(
+ new NativeMessageProcessHost(source_extension_id,
+ native_host_name,
+ launcher.Pass()));
return process.Pass();
}
void NativeMessageProcessHost::LaunchHostProcess() {
- DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ DCHECK(task_runner_->BelongsToCurrentThread());
GURL origin(std::string(kExtensionScheme) + "://" + source_extension_id_);
launcher_->Launch(origin, native_host_name_,
@@ -167,7 +110,7 @@ void NativeMessageProcessHost::OnHostProcessLaunched(
base::ProcessHandle process_handle,
base::File read_file,
base::File write_file) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ DCHECK(task_runner_->BelongsToCurrentThread());
switch (result) {
case NativeProcessLauncher::RESULT_INVALID_NAME:
@@ -204,8 +147,8 @@ void NativeMessageProcessHost::OnHostProcessLaunched(
DoWrite();
}
-void NativeMessageProcessHost::Send(const std::string& json) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+void NativeMessageProcessHost::OnMessage(const std::string& json) {
+ DCHECK(task_runner_->BelongsToCurrentThread());
if (closed_)
return;
@@ -229,6 +172,16 @@ void NativeMessageProcessHost::Send(const std::string& json) {
DoWrite();
}
+void NativeMessageProcessHost::Start(Client* client) {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ client_ = client;
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+NativeMessageProcessHost::task_runner() const {
+ return task_runner_;
+}
+
#if defined(OS_POSIX)
void NativeMessageProcessHost::OnFileCanReadWithoutBlocking(int fd) {
DCHECK_EQ(fd, read_file_);
@@ -264,7 +217,7 @@ void NativeMessageProcessHost::WaitRead() {
}
void NativeMessageProcessHost::DoRead() {
- DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ DCHECK(task_runner_->BelongsToCurrentThread());
while (!closed_ && !read_pending_) {
read_buffer_ = new net::IOBuffer(kReadBufferSize);
@@ -277,7 +230,7 @@ void NativeMessageProcessHost::DoRead() {
}
void NativeMessageProcessHost::OnRead(int result) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK(read_pending_);
read_pending_ = false;
@@ -286,7 +239,7 @@ void NativeMessageProcessHost::OnRead(int result) {
}
void NativeMessageProcessHost::HandleReadResult(int result) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ DCHECK(task_runner_->BelongsToCurrentThread());
if (closed_)
return;
@@ -307,7 +260,7 @@ void NativeMessageProcessHost::HandleReadResult(int result) {
void NativeMessageProcessHost::ProcessIncomingData(
const char* data, int data_size) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ DCHECK(task_runner_->BelongsToCurrentThread());
incoming_data_.append(data, data_size);
@@ -328,17 +281,15 @@ void NativeMessageProcessHost::ProcessIncomingData(
if (incoming_data_.size() < message_size + kMessageHeaderSize)
return;
- content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
- base::Bind(&Client::PostMessageFromNativeProcess, weak_client_ui_,
- destination_port_,
- incoming_data_.substr(kMessageHeaderSize, message_size)));
+ client_->PostMessageFromNativeHost(
+ incoming_data_.substr(kMessageHeaderSize, message_size));
incoming_data_.erase(0, kMessageHeaderSize + message_size);
}
}
void NativeMessageProcessHost::DoWrite() {
- DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ DCHECK(task_runner_->BelongsToCurrentThread());
while (!write_pending_ && !closed_) {
if (!current_write_buffer_.get() ||
@@ -360,7 +311,7 @@ void NativeMessageProcessHost::DoWrite() {
}
void NativeMessageProcessHost::HandleWriteResult(int result) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ DCHECK(task_runner_->BelongsToCurrentThread());
if (result <= 0) {
if (result == net::ERR_IO_PENDING) {
@@ -376,7 +327,7 @@ void NativeMessageProcessHost::HandleWriteResult(int result) {
}
void NativeMessageProcessHost::OnWritten(int result) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK(write_pending_);
write_pending_ = false;
@@ -386,15 +337,13 @@ void NativeMessageProcessHost::OnWritten(int result) {
}
void NativeMessageProcessHost::Close(const std::string& error_message) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ DCHECK(task_runner_->BelongsToCurrentThread());
if (!closed_) {
closed_ = true;
read_stream_.reset();
write_stream_.reset();
- content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
- base::Bind(&Client::CloseChannel, weak_client_ui_,
- destination_port_, error_message));
+ client_->CloseChannel(error_message);
}
if (process_handle_ != base::kNullProcessHandle) {
diff --git a/chrome/browser/extensions/api/messaging/native_message_process_host.h b/chrome/browser/extensions/api/messaging/native_message_process_host.h
index fb19240..58a202c 100644
--- a/chrome/browser/extensions/api/messaging/native_message_process_host.h
+++ b/chrome/browser/extensions/api/messaging/native_message_process_host.h
@@ -10,14 +10,12 @@
#include "base/files/file.h"
#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/process/process.h"
#include "chrome/browser/extensions/api/messaging/native_process_launcher.h"
+#include "extensions/browser/api/messaging/native_message_host.h"
#include "ui/gfx/native_widget_types.h"
-class PrefService;
-
namespace net {
class DrainableIOBuffer;
@@ -35,54 +33,25 @@ namespace extensions {
// This class must only be created, called, and deleted on the IO thread.
// Public methods typically accept callbacks which will be invoked on the UI
// thread.
-class NativeMessageProcessHost
+class NativeMessageProcessHost :
#if defined(OS_POSIX)
- : public base::MessageLoopForIO::Watcher
+ public base::MessageLoopForIO::Watcher,
#endif // !defined(OS_POSIX)
-{
+ public NativeMessageHost {
public:
- // Interface for the object that receives messages from the native process.
- class Client {
- public:
- virtual ~Client() {}
- // Called on the UI thread.
- virtual void PostMessageFromNativeProcess(int port_id,
- const std::string& message) = 0;
- virtual void CloseChannel(int port_id,
- const std::string& error_message) = 0;
- };
-
- // Result returned from IsHostAllowed().
- enum PolicyPermission {
- DISALLOW, // The host is not allowed.
- ALLOW_SYSTEM_ONLY, // Allowed only when installed on system level.
- ALLOW_ALL, // Allowed when installed on system or user level.
- };
-
virtual ~NativeMessageProcessHost();
- // Returns policy permissions for the host with the specified name.
- static PolicyPermission IsHostAllowed(const PrefService* pref_service,
- const std::string& native_host_name);
-
- static scoped_ptr<NativeMessageProcessHost> Create(
- gfx::NativeView native_view,
- base::WeakPtr<Client> weak_client_ui,
- const std::string& source_extension_id,
- const std::string& native_host_name,
- int destination_port,
- bool allow_user_level);
-
// Create using specified |launcher|. Used in tests.
- static scoped_ptr<NativeMessageProcessHost> CreateWithLauncher(
- base::WeakPtr<Client> weak_client_ui,
+ static scoped_ptr<NativeMessageHost> CreateWithLauncher(
const std::string& source_extension_id,
const std::string& native_host_name,
- int destination_port,
scoped_ptr<NativeProcessLauncher> launcher);
- // Send a message with the specified payload.
- void Send(const std::string& json);
+ // extensions::NativeMessageHost implementation.
+ virtual void OnMessage(const std::string& message) OVERRIDE;
+ virtual void Start(Client* client) OVERRIDE;
+ virtual scoped_refptr<base::SingleThreadTaskRunner> task_runner()
+ const OVERRIDE;
#if defined(OS_POSIX)
// MessageLoopForIO::Watcher interface
@@ -95,10 +64,8 @@ class NativeMessageProcessHost
void ReadNowForTesting();
private:
- NativeMessageProcessHost(base::WeakPtr<Client> weak_client_ui,
- const std::string& source_extension_id,
+ NativeMessageProcessHost(const std::string& source_extension_id,
const std::string& native_host_name,
- int destination_port,
scoped_ptr<NativeProcessLauncher> launcher);
// Starts the host process.
@@ -127,7 +94,7 @@ class NativeMessageProcessHost
// The Client messages will be posted to. Should only be accessed from the
// UI thread.
- base::WeakPtr<Client> weak_client_ui_;
+ Client* client_;
// ID of the calling extension.
std::string source_extension_id_;
@@ -135,10 +102,6 @@ class NativeMessageProcessHost
// Name of the native messaging host.
std::string native_host_name_;
- // The id of the port on the other side of this connection. This is passed to
- // |weak_client_ui_| when posting messages.
- int destination_port_;
-
// Launcher used to launch the native process.
scoped_ptr<NativeProcessLauncher> launcher_;
@@ -177,6 +140,8 @@ class NativeMessageProcessHost
// Set to true when a write is pending.
bool write_pending_;
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+
DISALLOW_COPY_AND_ASSIGN(NativeMessageProcessHost);
};
diff --git a/chrome/browser/extensions/api/messaging/native_message_process_host_unittest.cc b/chrome/browser/extensions/api/messaging/native_message_process_host_unittest.cc
index bb9c7a0..958c9c5 100644
--- a/chrome/browser/extensions/api/messaging/native_message_process_host_unittest.cc
+++ b/chrome/browser/extensions/api/messaging/native_message_process_host_unittest.cc
@@ -10,7 +10,6 @@
#include "base/files/scoped_temp_dir.h"
#include "base/json/json_reader.h"
#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/rand_util.h"
#include "base/run_loop.h"
@@ -93,7 +92,7 @@ class FakeLauncher : public NativeProcessLauncher {
};
class NativeMessagingTest : public ::testing::Test,
- public NativeMessageProcessHost::Client,
+ public NativeMessageHost::Client,
public base::SupportsWeakPtr<NativeMessagingTest> {
protected:
NativeMessagingTest()
@@ -106,16 +105,14 @@ class NativeMessagingTest : public ::testing::Test,
}
virtual void TearDown() override {
- if (native_message_process_host_.get()) {
- BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE,
- native_message_process_host_.release());
+ if (native_message_host_.get()) {
+ BrowserThread::DeleteSoon(
+ BrowserThread::IO, FROM_HERE, native_message_host_.release());
}
base::RunLoop().RunUntilIdle();
}
- virtual void PostMessageFromNativeProcess(
- int port_id,
- const std::string& message) override {
+ virtual void PostMessageFromNativeHost(const std::string& message) override {
last_message_ = message;
// Parse the message.
@@ -133,8 +130,7 @@ class NativeMessagingTest : public ::testing::Test,
run_loop_->Quit();
}
- virtual void CloseChannel(int port_id,
- const std::string& error_message) override {
+ virtual void CloseChannel(const std::string& error_message) override {
channel_closed_ = true;
if (run_loop_)
run_loop_->Quit();
@@ -164,7 +160,7 @@ class NativeMessagingTest : public ::testing::Test,
base::ScopedTempDir temp_dir_;
// Force the channel to be dev.
ScopedCurrentChannel current_channel_;
- scoped_ptr<NativeMessageProcessHost> native_message_process_host_;
+ scoped_ptr<NativeMessageHost> native_message_host_;
scoped_ptr<base::RunLoop> run_loop_;
content::TestBrowserThreadBundle thread_bundle_;
std::string last_message_;
@@ -180,15 +176,19 @@ TEST_F(NativeMessagingTest, SingleSendMessageRead) {
scoped_ptr<NativeProcessLauncher> launcher =
FakeLauncher::Create(temp_input_file, temp_output_file).Pass();
- native_message_process_host_ = NativeMessageProcessHost::CreateWithLauncher(
- AsWeakPtr(), ScopedTestNativeMessagingHost::kExtensionId, "empty_app.py",
- 0, launcher.Pass());
- ASSERT_TRUE(native_message_process_host_.get());
+ native_message_host_ = NativeMessageProcessHost::CreateWithLauncher(
+ ScopedTestNativeMessagingHost::kExtensionId,
+ "empty_app.py",
+ launcher.Pass());
+ native_message_host_->Start(this);
+ ASSERT_TRUE(native_message_host_.get());
run_loop_.reset(new base::RunLoop());
run_loop_->RunUntilIdle();
if (last_message_.empty()) {
run_loop_.reset(new base::RunLoop());
+ scoped_ptr<NativeMessageProcessHost> native_message_process_host_(
+ static_cast<NativeMessageProcessHost*>(native_message_host_.release()));
native_message_process_host_->ReadNowForTesting();
run_loop_->Run();
}
@@ -226,13 +226,15 @@ TEST_F(NativeMessagingTest, SingleSendMessageWrite) {
scoped_ptr<NativeProcessLauncher> launcher =
FakeLauncher::CreateWithPipeInput(read_file.Pass(),
temp_output_file).Pass();
- native_message_process_host_ = NativeMessageProcessHost::CreateWithLauncher(
- AsWeakPtr(), ScopedTestNativeMessagingHost::kExtensionId, "empty_app.py",
- 0, launcher.Pass());
- ASSERT_TRUE(native_message_process_host_.get());
+ native_message_host_ = NativeMessageProcessHost::CreateWithLauncher(
+ ScopedTestNativeMessagingHost::kExtensionId,
+ "empty_app.py",
+ launcher.Pass());
+ native_message_host_->Start(this);
+ ASSERT_TRUE(native_message_host_.get());
base::RunLoop().RunUntilIdle();
- native_message_process_host_->Send(kTestMessage);
+ native_message_host_->OnMessage(kTestMessage);
base::RunLoop().RunUntilIdle();
std::string output;
@@ -252,13 +254,17 @@ TEST_F(NativeMessagingTest, SingleSendMessageWrite) {
TEST_F(NativeMessagingTest, EchoConnect) {
ScopedTestNativeMessagingHost test_host;
ASSERT_NO_FATAL_FAILURE(test_host.RegisterTestHost(false));
-
- native_message_process_host_ = NativeMessageProcessHost::Create(
- NULL, AsWeakPtr(), ScopedTestNativeMessagingHost::kExtensionId,
- ScopedTestNativeMessagingHost::kHostName, 0, false);
- ASSERT_TRUE(native_message_process_host_.get());
-
- native_message_process_host_->Send("{\"text\": \"Hello.\"}");
+ std::string error_message;
+ native_message_host_ = NativeMessageProcessHost::Create(
+ NULL,
+ ScopedTestNativeMessagingHost::kExtensionId,
+ ScopedTestNativeMessagingHost::kHostName,
+ false,
+ &error_message);
+ native_message_host_->Start(this);
+ ASSERT_TRUE(native_message_host_.get());
+
+ native_message_host_->OnMessage("{\"text\": \"Hello.\"}");
run_loop_.reset(new base::RunLoop());
run_loop_->Run();
ASSERT_FALSE(last_message_.empty());
@@ -276,7 +282,7 @@ TEST_F(NativeMessagingTest, EchoConnect) {
EXPECT_TRUE(last_message_parsed_->GetString("caller_url", &url));
EXPECT_EQ(expected_url, url);
- native_message_process_host_->Send("{\"foo\": \"bar\"}");
+ native_message_host_->OnMessage("{\"foo\": \"bar\"}");
run_loop_.reset(new base::RunLoop());
run_loop_->Run();
EXPECT_TRUE(last_message_parsed_->GetInteger("id", &id));
@@ -291,12 +297,17 @@ TEST_F(NativeMessagingTest, UserLevel) {
ScopedTestNativeMessagingHost test_host;
ASSERT_NO_FATAL_FAILURE(test_host.RegisterTestHost(true));
- native_message_process_host_ = NativeMessageProcessHost::Create(
- NULL, AsWeakPtr(), ScopedTestNativeMessagingHost::kExtensionId,
- ScopedTestNativeMessagingHost::kHostName, 0, true);
- ASSERT_TRUE(native_message_process_host_.get());
-
- native_message_process_host_->Send("{\"text\": \"Hello.\"}");
+ std::string error_message;
+ native_message_host_ = NativeMessageProcessHost::Create(
+ NULL,
+ ScopedTestNativeMessagingHost::kExtensionId,
+ ScopedTestNativeMessagingHost::kHostName,
+ true,
+ &error_message);
+ native_message_host_->Start(this);
+ ASSERT_TRUE(native_message_host_.get());
+
+ native_message_host_->OnMessage("{\"text\": \"Hello.\"}");
run_loop_.reset(new base::RunLoop());
run_loop_->Run();
ASSERT_FALSE(last_message_.empty());
@@ -307,10 +318,15 @@ TEST_F(NativeMessagingTest, DisallowUserLevel) {
ScopedTestNativeMessagingHost test_host;
ASSERT_NO_FATAL_FAILURE(test_host.RegisterTestHost(true));
- native_message_process_host_ = NativeMessageProcessHost::Create(
- NULL, AsWeakPtr(), ScopedTestNativeMessagingHost::kExtensionId,
- ScopedTestNativeMessagingHost::kHostName, 0, false);
- ASSERT_TRUE(native_message_process_host_.get());
+ std::string error_message;
+ native_message_host_ = NativeMessageProcessHost::Create(
+ NULL,
+ ScopedTestNativeMessagingHost::kExtensionId,
+ ScopedTestNativeMessagingHost::kHostName,
+ false,
+ &error_message);
+ native_message_host_->Start(this);
+ ASSERT_TRUE(native_message_host_.get());
run_loop_.reset(new base::RunLoop());
run_loop_->Run();
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc
index e2cab92..1f7adc0 100644
--- a/chrome/browser/policy/policy_browsertest.cc
+++ b/chrome/browser/policy/policy_browsertest.cc
@@ -34,7 +34,7 @@
#include "chrome/browser/content_settings/tab_specific_content_settings.h"
#include "chrome/browser/devtools/devtools_window_testing.h"
#include "chrome/browser/download/download_prefs.h"
-#include "chrome/browser/extensions/api/messaging/native_message_process_host.h"
+#include "chrome/browser/extensions/api/messaging/message_service.h"
#include "chrome/browser/extensions/crx_installer.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/unpacked_installer.h"
@@ -3171,9 +3171,9 @@ IN_PROC_BROWSER_TEST_F(PolicyTest, NativeMessagingBlacklistSelective) {
UpdateProviderPolicy(policies);
PrefService* prefs = browser()->profile()->GetPrefs();
- EXPECT_FALSE(extensions::NativeMessageProcessHost::IsHostAllowed(
+ EXPECT_FALSE(extensions::MessageService::IsNativeMessagingHostAllowed(
prefs, "host.name"));
- EXPECT_TRUE(extensions::NativeMessageProcessHost::IsHostAllowed(
+ EXPECT_TRUE(extensions::MessageService::IsNativeMessagingHostAllowed(
prefs, "other.host.name"));
}
@@ -3186,9 +3186,9 @@ IN_PROC_BROWSER_TEST_F(PolicyTest, NativeMessagingBlacklistWildcard) {
UpdateProviderPolicy(policies);
PrefService* prefs = browser()->profile()->GetPrefs();
- EXPECT_FALSE(extensions::NativeMessageProcessHost::IsHostAllowed(
+ EXPECT_FALSE(extensions::MessageService::IsNativeMessagingHostAllowed(
prefs, "host.name"));
- EXPECT_FALSE(extensions::NativeMessageProcessHost::IsHostAllowed(
+ EXPECT_FALSE(extensions::MessageService::IsNativeMessagingHostAllowed(
prefs, "other.host.name"));
}
@@ -3205,9 +3205,9 @@ IN_PROC_BROWSER_TEST_F(PolicyTest, NativeMessagingWhitelist) {
UpdateProviderPolicy(policies);
PrefService* prefs = browser()->profile()->GetPrefs();
- EXPECT_TRUE(extensions::NativeMessageProcessHost::IsHostAllowed(
+ EXPECT_TRUE(extensions::MessageService::IsNativeMessagingHostAllowed(
prefs, "host.name"));
- EXPECT_FALSE(extensions::NativeMessageProcessHost::IsHostAllowed(
+ EXPECT_FALSE(extensions::MessageService::IsNativeMessagingHostAllowed(
prefs, "other.host.name"));
}
diff --git a/chrome/chrome_browser_extensions.gypi b/chrome/chrome_browser_extensions.gypi
index 25b5a99..021c9f8 100644
--- a/chrome/chrome_browser_extensions.gypi
+++ b/chrome/chrome_browser_extensions.gypi
@@ -22,6 +22,7 @@
'browser/extensions/api/log_private/log_private_api_chromeos.cc',
'browser/extensions/api/log_private/syslog_parser.cc',
'browser/extensions/api/log_private/syslog_parser.h',
+ 'browser/extensions/api/messaging/native_message_host_chromeos.cc',
'browser/extensions/api/terminal/terminal_extension_helper.cc',
'browser/extensions/api/terminal/terminal_extension_helper.h',
'browser/extensions/api/terminal/terminal_private_api.cc',
@@ -38,6 +39,12 @@
'browser/extensions/api/feedback_private/feedback_service_nonchromeos.cc',
'browser/extensions/api/image_writer_private/operation_nonchromeos.cc',
'browser/extensions/api/image_writer_private/removable_storage_provider_linux.cc',
+ 'browser/extensions/api/messaging/native_message_process_host.cc',
+ 'browser/extensions/api/messaging/native_message_process_host.h',
+ 'browser/extensions/api/messaging/native_process_launcher.cc',
+ 'browser/extensions/api/messaging/native_process_launcher.h',
+ 'browser/extensions/api/messaging/native_process_launcher_posix.cc',
+ 'browser/extensions/api/messaging/native_process_launcher_win.cc',
],
'chrome_browser_extensions_enabled_sources': [
'browser/apps/app_launch_for_metro_restart_win.cc',
@@ -325,16 +332,10 @@
'browser/extensions/api/messaging/message_service.h',
'browser/extensions/api/messaging/native_message_port.cc',
'browser/extensions/api/messaging/native_message_port.h',
- 'browser/extensions/api/messaging/native_message_process_host.cc',
- 'browser/extensions/api/messaging/native_message_process_host.h',
'browser/extensions/api/messaging/native_messaging_host_manifest.cc',
'browser/extensions/api/messaging/native_messaging_host_manifest.h',
'browser/extensions/api/messaging/native_messaging_policy_handler.cc',
'browser/extensions/api/messaging/native_messaging_policy_handler.h',
- 'browser/extensions/api/messaging/native_process_launcher.cc',
- 'browser/extensions/api/messaging/native_process_launcher.h',
- 'browser/extensions/api/messaging/native_process_launcher_posix.cc',
- 'browser/extensions/api/messaging/native_process_launcher_win.cc',
'browser/extensions/api/metrics_private/metrics_private_api.cc',
'browser/extensions/api/metrics_private/metrics_private_api.h',
'browser/extensions/api/module/module.cc',
diff --git a/chrome/test/data/extensions/api_test/native_messaging/test.js b/chrome/test/data/extensions/api_test/native_messaging/test.js
index 408c032..ab747a1 100644
--- a/chrome/test/data/extensions/api_test/native_messaging/test.js
+++ b/chrome/test/data/extensions/api_test/native_messaging/test.js
@@ -87,11 +87,8 @@ chrome.test.getConfig(function(config) {
function stopHost() {
port = chrome.extension.connectNative(appName);
- port.onMessage.addListener(function(message) {
- port.onDisconnect.addListener(chrome.test.callback(
- function() {},
- "Native host has exited."));
- });
+ port.onDisconnect.addListener(
+ chrome.test.callback(function() {}, "Native host has exited."));
// Send first message that should stop the host.
port.postMessage({ "stopHostTest": true });
diff --git a/extensions/browser/BUILD.gn b/extensions/browser/BUILD.gn
index 9ea3e4f..1825783 100644
--- a/extensions/browser/BUILD.gn
+++ b/extensions/browser/BUILD.gn
@@ -141,6 +141,7 @@ source_set("browser") {
"api/hid/hid_connection_resource.h",
"api/hid/hid_device_manager.cc",
"api/hid/hid_device_manager.h",
+ "api/messaging/native_message_host.cc",
"api/power/power_api.cc",
"api/power/power_api.h",
"api/power/power_api_manager.cc",
diff --git a/extensions/browser/api/messaging/native_message_host.cc b/extensions/browser/api/messaging/native_message_host.cc
new file mode 100644
index 0000000..f3bb082
--- /dev/null
+++ b/extensions/browser/api/messaging/native_message_host.cc
@@ -0,0 +1,21 @@
+// Copyright 2014 The Chromium 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 "extensions/browser/api/messaging/native_message_host.h"
+
+namespace extensions {
+
+const char NativeMessageHost::kFailedToStartError[] =
+ "Failed to start native messaging host.";
+const char NativeMessageHost::kInvalidNameError[] =
+ "Invalid native messaging host name specified.";
+const char NativeMessageHost::kNativeHostExited[] = "Native host has exited.";
+const char NativeMessageHost::kNotFoundError[] =
+ "Specified native messaging host not found.";
+const char NativeMessageHost::kForbiddenError[] =
+ "Access to the specified native messaging host is forbidden.";
+const char NativeMessageHost::kHostInputOuputError[] =
+ "Error when communicating with the native messaging host.";
+
+} // extensions
diff --git a/extensions/browser/api/messaging/native_message_host.h b/extensions/browser/api/messaging/native_message_host.h
new file mode 100644
index 0000000..da241e0
--- /dev/null
+++ b/extensions/browser/api/messaging/native_message_host.h
@@ -0,0 +1,62 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef EXTENSIONS_BROWSER_API_MESSAGING_NATIVE_MESSAGE_HOST_H_
+#define EXTENSIONS_BROWSER_API_MESSAGING_NATIVE_MESSAGE_HOST_H_
+
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/single_thread_task_runner.h"
+#include "ui/gfx/native_widget_types.h"
+
+namespace extensions {
+
+// An interface for receiving messages from MessageService (Chrome) using the
+// Native Messaging API. A NativeMessageHost object hosts a native component,
+// which can run in the browser-process or in a separate process (See
+// NativeMessageProcessHost).
+class NativeMessageHost {
+ public:
+ static const char kFailedToStartError[];
+ static const char kInvalidNameError[];
+ static const char kNativeHostExited[];
+ static const char kNotFoundError[];
+ static const char kForbiddenError[];
+ static const char kHostInputOuputError[];
+
+ // Callback interface for receiving messages from the native host.
+ class Client {
+ public:
+ virtual ~Client() {}
+
+ // Called on the UI thread.
+ virtual void PostMessageFromNativeHost(const std::string& message) = 0;
+ virtual void CloseChannel(const std::string& error_message) = 0;
+ };
+
+ // Creates the NativeMessageHost based on the |native_host_name|.
+ static scoped_ptr<NativeMessageHost> Create(
+ gfx::NativeView native_view,
+ const std::string& source_extension_id,
+ const std::string& native_host_name,
+ bool allow_user_level,
+ std::string* error);
+
+ virtual ~NativeMessageHost() {}
+
+ // Called when a message is received from MessageService (Chrome).
+ virtual void OnMessage(const std::string& message) = 0;
+
+ // Sets the client to start receiving messages from the native host.
+ virtual void Start(Client* client) = 0;
+
+ // Returns the task runner that the host runs on. The Client should only
+ // invoke OnMessage() on this task runner.
+ virtual scoped_refptr<base::SingleThreadTaskRunner> task_runner() const = 0;
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_BROWSER_API_MESSAGING_NATIVE_MESSAGE_HOST_H_
diff --git a/extensions/common/switches.cc b/extensions/common/switches.cc
index 5c44c84..d9eba9e 100644
--- a/extensions/common/switches.cc
+++ b/extensions/common/switches.cc
@@ -62,6 +62,10 @@ const char kEnableMimeHandlerView[] = "enable-mime-handler-view";
// Enables extensions to hide bookmarks UI elements.
const char kEnableOverrideBookmarksUI[] = "enable-override-bookmarks-ui";
+// Allows remote assistance connection to this computer using the Chrome Remote
+// Desktop app on Chrome OS.
+const char kEnableRemoteAssistance[] = "enable-remote-assistance";
+
// Allows the ErrorConsole to collect runtime and manifest errors, and display
// them in the chrome:extensions page.
const char kErrorConsole[] = "error-console";
diff --git a/extensions/common/switches.h b/extensions/common/switches.h
index 4aa10ea..59fadb2 100644
--- a/extensions/common/switches.h
+++ b/extensions/common/switches.h
@@ -25,6 +25,7 @@ extern const char kEnableExtensionActionRedesign[];
extern const char kEnableExtensionInfoDialog[];
extern const char kEnableMimeHandlerView[];
extern const char kEnableOverrideBookmarksUI[];
+extern const char kEnableRemoteAssistance[];
extern const char kErrorConsole[];
extern const char kExtensionActionRedesign[];
extern const char kExtensionProcess[];
diff --git a/extensions/extensions.gyp b/extensions/extensions.gyp
index 0a80101..ac1eb6e 100644
--- a/extensions/extensions.gyp
+++ b/extensions/extensions.gyp
@@ -426,6 +426,7 @@
'browser/api/hid/hid_connection_resource.h',
'browser/api/hid/hid_device_manager.cc',
'browser/api/hid/hid_device_manager.h',
+ 'browser/api/messaging/native_message_host.cc',
'browser/api/power/power_api.cc',
'browser/api/power/power_api.h',
'browser/api/power/power_api_manager.cc',
diff --git a/remoting/host/it2me/com.google.chrome.remote_assistance.json.jinja2 b/remoting/host/it2me/com.google.chrome.remote_assistance.json.jinja2
index 9c90357..5545dc8 100644
--- a/remoting/host/it2me/com.google.chrome.remote_assistance.json.jinja2
+++ b/remoting/host/it2me/com.google.chrome.remote_assistance.json.jinja2
@@ -3,6 +3,9 @@
"description": "{{ IT2ME_HOST_DESCRIPTION }}",
"type": "stdio",
"path": "{{ IT2ME_HOST_PATH }}",
+ // If you modify the list of allowed_origins, don't forget to update
+ // chrome/browser/extensions/messaging/native_message_host_chromeos.cc
+ // to keep the two lists in sync.
"allowed_origins": [
"chrome-extension://ljacajndfccfgnfohlgkdphmbnpkjflk/",
"chrome-extension://gbchcmhmhahfdphkhkmpfmihenigjmpp/",
diff --git a/remoting/host/it2me/it2me_native_messaging_host.cc b/remoting/host/it2me/it2me_native_messaging_host.cc
index 8d0d131..24ddc1b 100644
--- a/remoting/host/it2me/it2me_native_messaging_host.cc
+++ b/remoting/host/it2me/it2me_native_messaging_host.cc
@@ -9,9 +9,8 @@
#include "base/basictypes.h"
#include "base/bind.h"
#include "base/callback.h"
-#include "base/callback_helpers.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
+#include "base/json/json_reader.h"
+#include "base/json/json_writer.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringize_macros.h"
#include "base/threading/thread.h"
@@ -42,9 +41,8 @@ const remoting::protocol::NameMapElement<It2MeHostState> kIt2MeHostStates[] = {
It2MeNativeMessagingHost::It2MeNativeMessagingHost(
scoped_refptr<AutoThreadTaskRunner> task_runner,
- scoped_ptr<extensions::NativeMessagingChannel> channel,
scoped_ptr<It2MeHostFactory> factory)
- : channel_(channel.Pass()),
+ : client_(NULL),
factory_(factory.Pass()),
weak_factory_(this) {
weak_ptr_ = weak_factory_.GetWeakPtr();
@@ -75,27 +73,19 @@ It2MeNativeMessagingHost::~It2MeNativeMessagingHost() {
}
}
-void It2MeNativeMessagingHost::Start(const base::Closure& quit_closure) {
+void It2MeNativeMessagingHost::OnMessage(const std::string& message) {
DCHECK(task_runner()->BelongsToCurrentThread());
- DCHECK(!quit_closure.is_null());
- quit_closure_ = quit_closure;
-
- channel_->Start(this);
-}
-
-void It2MeNativeMessagingHost::OnMessage(scoped_ptr<base::Value> message) {
- DCHECK(task_runner()->BelongsToCurrentThread());
-
- if (!message->IsType(base::Value::TYPE_DICTIONARY)) {
+ scoped_ptr<base::DictionaryValue> response(new base::DictionaryValue());
+ scoped_ptr<base::Value> message_value(base::JSONReader::Read(message));
+ if (!message_value->IsType(base::Value::TYPE_DICTIONARY)) {
LOG(ERROR) << "Received a message that's not a dictionary.";
- channel_->SendMessage(nullptr);
+ client_->CloseChannel(std::string());
return;
}
scoped_ptr<base::DictionaryValue> message_dict(
- static_cast<base::DictionaryValue*>(message.release()));
- scoped_ptr<base::DictionaryValue> response(new base::DictionaryValue());
+ static_cast<base::DictionaryValue*>(message_value.release()));
// If the client supplies an ID, it will expect it in the response. This
// might be a string or a number, so cope with both.
@@ -122,9 +112,17 @@ void It2MeNativeMessagingHost::OnMessage(scoped_ptr<base::Value> message) {
}
}
-void It2MeNativeMessagingHost::OnDisconnect() {
- if (!quit_closure_.is_null())
- base::ResetAndReturn(&quit_closure_).Run();
+void It2MeNativeMessagingHost::Start(Client* client) {
+ DCHECK(task_runner()->BelongsToCurrentThread());
+ client_ = client;
+}
+
+void It2MeNativeMessagingHost::SendMessageToClient(
+ scoped_ptr<base::DictionaryValue> message) const {
+ DCHECK(task_runner()->BelongsToCurrentThread());
+ std::string message_json;
+ base::JSONWriter::Write(message.get(), &message_json);
+ client_->PostMessageFromNativeHost(message_json);
}
void It2MeNativeMessagingHost::ProcessHello(
@@ -138,7 +136,7 @@ void It2MeNativeMessagingHost::ProcessHello(
scoped_ptr<base::ListValue> supported_features_list(new base::ListValue());
response->Set("supportedFeatures", supported_features_list.release());
- channel_->SendMessage(response.Pass());
+ SendMessageToClient(response.Pass());
}
void It2MeNativeMessagingHost::ProcessConnect(
@@ -212,7 +210,7 @@ void It2MeNativeMessagingHost::ProcessConnect(
directory_bot_jid_);
it2me_host_->Connect();
- channel_->SendMessage(response.Pass());
+ SendMessageToClient(response.Pass());
}
void It2MeNativeMessagingHost::ProcessDisconnect(
@@ -224,7 +222,7 @@ void It2MeNativeMessagingHost::ProcessDisconnect(
it2me_host_->Disconnect();
it2me_host_ = NULL;
}
- channel_->SendMessage(response.Pass());
+ SendMessageToClient(response.Pass());
}
void It2MeNativeMessagingHost::SendErrorAndExit(
@@ -236,10 +234,10 @@ void It2MeNativeMessagingHost::SendErrorAndExit(
response->SetString("type", "error");
response->SetString("description", description);
- channel_->SendMessage(response.Pass());
+ SendMessageToClient(response.Pass());
- // Trigger a host shutdown by sending a NULL message.
- channel_->SendMessage(nullptr);
+ // Trigger a host shutdown by sending an empty message.
+ client_->CloseChannel(std::string());
}
void It2MeNativeMessagingHost::OnStateChanged(It2MeHostState state) {
@@ -272,7 +270,7 @@ void It2MeNativeMessagingHost::OnStateChanged(It2MeHostState state) {
;
}
- channel_->SendMessage(message.Pass());
+ SendMessageToClient(message.Pass());
}
void It2MeNativeMessagingHost::OnNatPolicyChanged(bool nat_traversal_enabled) {
@@ -282,7 +280,7 @@ void It2MeNativeMessagingHost::OnNatPolicyChanged(bool nat_traversal_enabled) {
message->SetString("type", "natPolicyChanged");
message->SetBoolean("natTraversalEnabled", nat_traversal_enabled);
- channel_->SendMessage(message.Pass());
+ SendMessageToClient(message.Pass());
}
// Stores the Access Code for the web-app to query.
@@ -303,7 +301,7 @@ void It2MeNativeMessagingHost::OnClientAuthenticated(
client_username_ = client_username;
}
-scoped_refptr<AutoThreadTaskRunner>
+scoped_refptr<base::SingleThreadTaskRunner>
It2MeNativeMessagingHost::task_runner() const {
return host_context_->ui_task_runner();
}
diff --git a/remoting/host/it2me/it2me_native_messaging_host.h b/remoting/host/it2me/it2me_native_messaging_host.h
index f9d8ac9..18e738b 100644
--- a/remoting/host/it2me/it2me_native_messaging_host.h
+++ b/remoting/host/it2me/it2me_native_messaging_host.h
@@ -8,40 +8,38 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
-#include "extensions/browser/api/messaging/native_messaging_channel.h"
+#include "extensions/browser/api/messaging/native_message_host.h"
#include "remoting/base/auto_thread_task_runner.h"
#include "remoting/host/it2me/it2me_host.h"
namespace base {
class DictionaryValue;
+class Value;
} // namespace base
namespace remoting {
// Implementation of the native messaging host process.
-class It2MeNativeMessagingHost
- : public It2MeHost::Observer,
- public extensions::NativeMessagingChannel::EventHandler {
+class It2MeNativeMessagingHost : public It2MeHost::Observer,
+ public extensions::NativeMessageHost {
public:
- It2MeNativeMessagingHost(
- scoped_refptr<AutoThreadTaskRunner> task_runner,
- scoped_ptr<extensions::NativeMessagingChannel> channel,
- scoped_ptr<It2MeHostFactory> factory);
+ It2MeNativeMessagingHost(scoped_refptr<AutoThreadTaskRunner> task_runner,
+ scoped_ptr<It2MeHostFactory> factory);
virtual ~It2MeNativeMessagingHost();
- void Start(const base::Closure& quit_closure);
-
- // extensions::NativeMessagingChannel::EventHandler implementation.
- virtual void OnMessage(scoped_ptr<base::Value> message) OVERRIDE;
- virtual void OnDisconnect() OVERRIDE;
+ // extensions::NativeMessageHost implementation.
+ virtual void OnMessage(const std::string& message) override;
+ virtual void Start(Client* client) override;
+ virtual scoped_refptr<base::SingleThreadTaskRunner> task_runner()
+ const override;
// It2MeHost::Observer implementation.
virtual void OnClientAuthenticated(const std::string& client_username)
- OVERRIDE;
+ override;
virtual void OnStoreAccessCode(const std::string& access_code,
- base::TimeDelta access_code_lifetime) OVERRIDE;
- virtual void OnNatPolicyChanged(bool nat_traversal_enabled) OVERRIDE;
- virtual void OnStateChanged(It2MeHostState state) OVERRIDE;
+ base::TimeDelta access_code_lifetime) override;
+ virtual void OnNatPolicyChanged(bool nat_traversal_enabled) override;
+ virtual void OnStateChanged(It2MeHostState state) override;
static std::string HostStateToString(It2MeHostState host_state);
@@ -57,12 +55,9 @@ class It2MeNativeMessagingHost
scoped_ptr<base::DictionaryValue> response);
void SendErrorAndExit(scoped_ptr<base::DictionaryValue> response,
const std::string& description) const;
+ void SendMessageToClient(scoped_ptr<base::DictionaryValue> message) const;
- base::Closure quit_closure_;
-
- scoped_refptr<AutoThreadTaskRunner> task_runner() const;
-
- scoped_ptr<extensions::NativeMessagingChannel> channel_;
+ Client* client_;
scoped_ptr<It2MeHostFactory> factory_;
scoped_ptr<ChromotingHostContext> host_context_;
scoped_refptr<It2MeHost> it2me_host_;
diff --git a/remoting/host/it2me/it2me_native_messaging_host_main.cc b/remoting/host/it2me/it2me_native_messaging_host_main.cc
index 25f5021..7d27d19 100644
--- a/remoting/host/it2me/it2me_native_messaging_host_main.cc
+++ b/remoting/host/it2me/it2me_native_messaging_host_main.cc
@@ -16,6 +16,7 @@
#include "remoting/host/host_exit_codes.h"
#include "remoting/host/it2me/it2me_native_messaging_host.h"
#include "remoting/host/logging.h"
+#include "remoting/host/native_messaging/native_messaging_pipe.h"
#include "remoting/host/native_messaging/pipe_messaging_channel.h"
#include "remoting/host/usage_stats_consent.h"
@@ -117,13 +118,21 @@ int StartIt2MeNativeMessagingHost() {
scoped_ptr<It2MeHostFactory> factory(new It2MeHostFactory());
+ scoped_ptr<NativeMessagingPipe> native_messaging_pipe(
+ new NativeMessagingPipe());
+
// Set up the native messaging channel.
scoped_ptr<extensions::NativeMessagingChannel> channel(
new PipeMessagingChannel(read_file.Pass(), write_file.Pass()));
- scoped_ptr<It2MeNativeMessagingHost> host(new It2MeNativeMessagingHost(
- task_runner, channel.Pass(), factory.Pass()));
- host->Start(run_loop.QuitClosure());
+ scoped_ptr<extensions::NativeMessageHost> host(new It2MeNativeMessagingHost(
+ task_runner,
+ factory.Pass()));
+
+ host->Start(native_messaging_pipe.get());
+
+ native_messaging_pipe->Start(
+ host.Pass(), channel.Pass(), run_loop.QuitClosure());
// Run the loop until channel is alive.
run_loop.Run();
diff --git a/remoting/host/it2me/it2me_native_messaging_host_unittest.cc b/remoting/host/it2me/it2me_native_messaging_host_unittest.cc
index 56515a9..61334cf 100644
--- a/remoting/host/it2me/it2me_native_messaging_host_unittest.cc
+++ b/remoting/host/it2me/it2me_native_messaging_host_unittest.cc
@@ -17,6 +17,7 @@
#include "net/base/net_util.h"
#include "remoting/base/auto_thread_task_runner.h"
#include "remoting/host/chromoting_host_context.h"
+#include "remoting/host/native_messaging/native_messaging_pipe.h"
#include "remoting/host/native_messaging/pipe_messaging_channel.h"
#include "remoting/host/setup/test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -78,9 +79,9 @@ class MockIt2MeHost : public It2MeHost {
directory_bot_jid) {}
// It2MeHost overrides
- virtual void Connect() OVERRIDE;
- virtual void Disconnect() OVERRIDE;
- virtual void RequestNatPolicy() OVERRIDE;
+ virtual void Connect() override;
+ virtual void Disconnect() override;
+ virtual void RequestNatPolicy() override;
private:
virtual ~MockIt2MeHost() {}
@@ -153,7 +154,7 @@ class MockIt2MeHostFactory : public It2MeHostFactory {
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
base::WeakPtr<It2MeHost::Observer> observer,
const XmppSignalStrategy::XmppServerConfig& xmpp_server_config,
- const std::string& directory_bot_jid) OVERRIDE {
+ const std::string& directory_bot_jid) override {
return new MockIt2MeHost(
context, task_runner, observer, xmpp_server_config, directory_bot_jid);
}
@@ -167,8 +168,8 @@ class It2MeNativeMessagingHostTest : public testing::Test {
It2MeNativeMessagingHostTest() {}
virtual ~It2MeNativeMessagingHostTest() {}
- virtual void SetUp() OVERRIDE;
- virtual void TearDown() OVERRIDE;
+ virtual void SetUp() override;
+ virtual void TearDown() override;
protected:
scoped_ptr<base::DictionaryValue> ReadMessageFromOutputPipe();
@@ -209,7 +210,7 @@ class It2MeNativeMessagingHostTest : public testing::Test {
// Task runner of the host thread.
scoped_refptr<AutoThreadTaskRunner> host_task_runner_;
- scoped_ptr<remoting::It2MeNativeMessagingHost> host_;
+ scoped_ptr<remoting::NativeMessagingPipe> pipe_;
DISALLOW_COPY_AND_ASSIGN(It2MeNativeMessagingHostTest);
};
@@ -431,15 +432,21 @@ void It2MeNativeMessagingHostTest::StartHost() {
// Creating a native messaging host with a mock It2MeHostFactory.
scoped_ptr<It2MeHostFactory> factory(new MockIt2MeHostFactory());
+ pipe_.reset(new NativeMessagingPipe());
+
scoped_ptr<extensions::NativeMessagingChannel> channel(
new PipeMessagingChannel(input_read_file.Pass(),
output_write_file.Pass()));
- host_.reset(new It2MeNativeMessagingHost(
- host_task_runner_,
- channel.Pass(),
- factory.Pass()));
- host_->Start(base::Bind(&It2MeNativeMessagingHostTest::StopHost,
+ scoped_ptr<extensions::NativeMessageHost> it2me_host(
+ new It2MeNativeMessagingHost(
+ host_task_runner_,
+ factory.Pass()));
+ it2me_host->Start(pipe_.get());
+
+ pipe_->Start(it2me_host.Pass(),
+ channel.Pass(),
+ base::Bind(&It2MeNativeMessagingHostTest::StopHost,
base::Unretained(this)));
// Notify the test that the host has finished starting up.
@@ -450,7 +457,7 @@ void It2MeNativeMessagingHostTest::StartHost() {
void It2MeNativeMessagingHostTest::StopHost() {
DCHECK(host_task_runner_->RunsTasksOnCurrentThread());
- host_.reset();
+ pipe_.reset();
// Wait till all shutdown tasks have completed.
base::RunLoop().RunUntilIdle();
diff --git a/remoting/host/native_messaging/native_messaging_pipe.cc b/remoting/host/native_messaging/native_messaging_pipe.cc
new file mode 100644
index 0000000..13abc35
--- /dev/null
+++ b/remoting/host/native_messaging/native_messaging_pipe.cc
@@ -0,0 +1,52 @@
+// Copyright 2014 The Chromium 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 "remoting/host/native_messaging/native_messaging_pipe.h"
+
+#include "base/callback_helpers.h"
+#include "base/json/json_reader.h"
+#include "base/json/json_writer.h"
+#include "base/values.h"
+
+namespace remoting {
+
+NativeMessagingPipe::NativeMessagingPipe() {
+}
+
+NativeMessagingPipe::~NativeMessagingPipe() {
+}
+
+void NativeMessagingPipe::Start(
+ scoped_ptr<extensions::NativeMessageHost> host,
+ scoped_ptr<extensions::NativeMessagingChannel> channel,
+ const base::Closure& quit_closure) {
+ host_ = host.Pass();
+ channel_ = channel.Pass();
+ quit_closure_ = quit_closure;
+ channel_->Start(this);
+}
+
+void NativeMessagingPipe::OnMessage(scoped_ptr<base::Value> message) {
+ std::string message_json;
+ base::JSONWriter::Write(message.get(), &message_json);
+ host_->OnMessage(message_json);
+}
+
+void NativeMessagingPipe::OnDisconnect() {
+ if (!quit_closure_.is_null())
+ base::ResetAndReturn(&quit_closure_).Run();
+}
+
+void NativeMessagingPipe::PostMessageFromNativeHost(
+ const std::string& message) {
+ scoped_ptr<base::Value> json(base::JSONReader::Read(message));
+ channel_->SendMessage(json.Pass());
+}
+
+void NativeMessagingPipe::CloseChannel(const std::string& error_message) {
+ if (!quit_closure_.is_null())
+ base::ResetAndReturn(&quit_closure_).Run();
+}
+
+} // namespace remoting
diff --git a/remoting/host/native_messaging/native_messaging_pipe.h b/remoting/host/native_messaging/native_messaging_pipe.h
new file mode 100644
index 0000000..24a16f7
--- /dev/null
+++ b/remoting/host/native_messaging/native_messaging_pipe.h
@@ -0,0 +1,50 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef REMOTING_HOST_NATIVE_MESSAGING_NATIVE_MESSAGING_PIPE_H_
+#define REMOTING_HOST_NATIVE_MESSAGING_NATIVE_MESSAGING_PIPE_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "extensions/browser/api/messaging/native_message_host.h"
+#include "extensions/browser/api/messaging/native_messaging_channel.h"
+
+namespace base {
+class Value;
+}
+
+namespace remoting {
+
+// Connects a extensions::NativeMessageHost to a PipeMessagingChannel.
+class NativeMessagingPipe
+ : public extensions::NativeMessagingChannel::EventHandler,
+ public extensions::NativeMessageHost::Client {
+ public:
+ NativeMessagingPipe();
+ virtual ~NativeMessagingPipe();
+
+ // Starts processing messages from the pipe.
+ void Start(scoped_ptr<extensions::NativeMessageHost> host,
+ scoped_ptr<extensions::NativeMessagingChannel> channel,
+ const base::Closure& quit_closure);
+
+ // extensions::NativeMessageHost::Client implementation.
+ virtual void PostMessageFromNativeHost(const std::string& message) override;
+ virtual void CloseChannel(const std::string& error_message) override;
+
+ // extensions::NativeMessagingChannel::EventHandler implementation.
+ virtual void OnMessage(scoped_ptr<base::Value> message) override;
+ virtual void OnDisconnect() override;
+
+ private:
+ base::Closure quit_closure_;
+ scoped_ptr<extensions::NativeMessagingChannel> channel_;
+ scoped_ptr<extensions::NativeMessageHost> host_;
+
+ DISALLOW_COPY_AND_ASSIGN(NativeMessagingPipe);
+};
+
+} // namespace remoting
+
+#endif // REMOTING_HOST_NATIVE_MESSAGING_NATIVE_MESSAGING_PIPE_H_
diff --git a/remoting/remoting_host.gypi b/remoting/remoting_host.gypi
index eca5646..5538700 100644
--- a/remoting/remoting_host.gypi
+++ b/remoting/remoting_host.gypi
@@ -431,6 +431,8 @@
'sources': [
'host/native_messaging/pipe_messaging_channel.cc',
'host/native_messaging/pipe_messaging_channel.h',
+ 'host/native_messaging/native_messaging_pipe.cc',
+ 'host/native_messaging/native_messaging_pipe.h',
'host/native_messaging/native_messaging_reader.cc',
'host/native_messaging/native_messaging_reader.h',
'host/native_messaging/native_messaging_writer.cc',
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index b40c638..ce268d5 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -45886,6 +45886,7 @@ To add a new entry, add it with any value and run test to compute valid value.
<int value="880510010" label="enable-permissions-bubbles"/>
<int value="887011602" label="enable-spelling-auto-correct"/>
<int value="909439558" label="disable-device-discovery"/>
+ <int value="952558794" label="enable-remote-assistance"/>
<int value="1022992701" label="enable-origin-chip-always"/>
<int value="1033597574" label="disable-layer-squashing"/>
<int value="1050321458" label="new-profile-management"/>