// Copyright (c) 2012 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 "chrome/browser/extensions/api/messaging/native_message_port.h" #include "base/bind.h" #include "base/single_thread_task_runner.h" #include "base/thread_task_runner_handle.h" #include "chrome/browser/extensions/api/messaging/native_message_process_host.h" #include "content/public/browser/browser_thread.h" namespace extensions { // 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 host, base::WeakPtr port, scoped_refptr message_service_task_runner_); ~Core() override; void OnMessageFromChrome(const std::string& message); // NativeMessageHost::Client implementation. void PostMessageFromNativeHost(const std::string& message) override; void CloseChannel(const std::string& error_message) override; private: scoped_ptr host_; base::WeakPtr port_; scoped_refptr message_service_task_runner_; scoped_refptr host_task_runner_; }; NativeMessagePort::Core::Core( scoped_ptr host, base::WeakPtr port, scoped_refptr 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 message_service, int port_id, scoped_ptr 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::ThreadTaskRunnerHandle::Get())); } NativeMessagePort::~NativeMessagePort() { DCHECK(thread_checker_.CalledOnValidThread()); host_task_runner_->DeleteSoon(FROM_HERE, core_.release()); } void NativeMessagePort::DispatchOnMessage( const Message& message, int target_port_id) { 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