summaryrefslogtreecommitdiffstats
path: root/chrome/browser/extensions/api/messaging/native_message_port.cc
blob: 66b1674e2e45dcd36a0dc0a4cbe08389fbf26736 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// 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 "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<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() {
  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