1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "ipc/mojo/ipc_channel_mojo_host.h"
6
7#include "base/bind.h"
8#include "base/message_loop/message_loop.h"
9#include "ipc/mojo/ipc_channel_mojo.h"
10
11namespace IPC {
12
13// The delete class lives on the IO thread to talk to ChannelMojo on
14// behalf of ChannelMojoHost.
15//
16// The object must be touched only on the IO thread.
17class ChannelMojoHost::ChannelDelegate : public ChannelMojo::Delegate {
18 public:
19  explicit ChannelDelegate(scoped_refptr<base::TaskRunner> io_task_runner);
20  virtual ~ChannelDelegate();
21
22  // ChannelMojo::Delegate
23  virtual base::WeakPtr<Delegate> ToWeakPtr() OVERRIDE;
24  virtual void OnChannelCreated(base::WeakPtr<ChannelMojo> channel) OVERRIDE;
25  virtual scoped_refptr<base::TaskRunner> GetIOTaskRunner() OVERRIDE;
26
27  // Returns an weak ptr of ChannelDelegate instead of Delegate
28  base::WeakPtr<ChannelDelegate> GetWeakPtr();
29  void OnClientLaunched(base::ProcessHandle process);
30  void DeleteThisSoon();
31
32 private:
33  scoped_refptr<base::TaskRunner> io_task_runner_;
34  base::WeakPtrFactory<ChannelDelegate> weak_factory_;
35  base::WeakPtr<ChannelMojo> channel_;
36
37  DISALLOW_COPY_AND_ASSIGN(ChannelDelegate);
38};
39
40ChannelMojoHost::ChannelDelegate::ChannelDelegate(
41    scoped_refptr<base::TaskRunner> io_task_runner)
42    : io_task_runner_(io_task_runner), weak_factory_(this) {
43}
44
45ChannelMojoHost::ChannelDelegate::~ChannelDelegate() {
46}
47
48base::WeakPtr<ChannelMojo::Delegate>
49ChannelMojoHost::ChannelDelegate::ToWeakPtr() {
50  return weak_factory_.GetWeakPtr();
51}
52
53base::WeakPtr<ChannelMojoHost::ChannelDelegate>
54ChannelMojoHost::ChannelDelegate::GetWeakPtr() {
55  return weak_factory_.GetWeakPtr();
56}
57
58void ChannelMojoHost::ChannelDelegate::OnChannelCreated(
59    base::WeakPtr<ChannelMojo> channel) {
60  DCHECK(!channel_);
61  channel_ = channel;
62}
63
64scoped_refptr<base::TaskRunner>
65ChannelMojoHost::ChannelDelegate::GetIOTaskRunner() {
66  return io_task_runner_;
67}
68
69void ChannelMojoHost::ChannelDelegate::OnClientLaunched(
70    base::ProcessHandle process) {
71  if (channel_)
72    channel_->OnClientLaunched(process);
73}
74
75void ChannelMojoHost::ChannelDelegate::DeleteThisSoon() {
76  io_task_runner_->PostTask(
77      FROM_HERE,
78      base::Bind(&base::DeletePointer<ChannelMojoHost::ChannelDelegate>,
79                 base::Unretained(this)));
80}
81
82//
83// ChannelMojoHost
84//
85
86ChannelMojoHost::ChannelMojoHost(scoped_refptr<base::TaskRunner> io_task_runner)
87    : weak_factory_(this),
88      io_task_runner_(io_task_runner),
89      channel_delegate_(new ChannelDelegate(io_task_runner)) {
90}
91
92ChannelMojoHost::~ChannelMojoHost() {
93}
94
95void ChannelMojoHost::OnClientLaunched(base::ProcessHandle process) {
96  if (io_task_runner_ == base::MessageLoop::current()->message_loop_proxy()) {
97    channel_delegate_->OnClientLaunched(process);
98  } else {
99    io_task_runner_->PostTask(FROM_HERE,
100                              base::Bind(&ChannelDelegate::OnClientLaunched,
101                                         channel_delegate_->GetWeakPtr(),
102                                         process));
103  }
104}
105
106ChannelMojo::Delegate* ChannelMojoHost::channel_delegate() const {
107  return channel_delegate_.get();
108}
109
110void ChannelMojoHost::DelegateDeleter::operator()(
111    ChannelMojoHost::ChannelDelegate* ptr) const {
112  ptr->DeleteThisSoon();
113}
114
115}  // namespace IPC
116