1// Copyright (c) 2012 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#ifndef CHROME_BROWSER_EXTENSIONS_API_MESSAGING_NATIVE_MESSAGE_PROCESS_HOST_H_
6#define CHROME_BROWSER_EXTENSIONS_API_MESSAGING_NATIVE_MESSAGE_PROCESS_HOST_H_
7
8#include <queue>
9#include <string>
10
11#include "base/files/file.h"
12#include "base/memory/scoped_ptr.h"
13#include "base/memory/weak_ptr.h"
14#include "base/message_loop/message_loop.h"
15#include "base/process/process.h"
16#include "chrome/browser/extensions/api/messaging/native_process_launcher.h"
17#include "ui/gfx/native_widget_types.h"
18
19class PrefService;
20
21namespace net {
22
23class DrainableIOBuffer;
24class FileStream;
25class IOBuffer;
26class IOBufferWithSize;
27
28}  // namespace net
29
30namespace extensions {
31
32// Manages the native side of a connection between an extension and a native
33// process.
34//
35// This class must only be created, called, and deleted on the IO thread.
36// Public methods typically accept callbacks which will be invoked on the UI
37// thread.
38class NativeMessageProcessHost
39#if defined(OS_POSIX)
40    : public base::MessageLoopForIO::Watcher
41#endif  // !defined(OS_POSIX)
42{
43 public:
44  // Interface for the object that receives messages from the native process.
45  class Client {
46   public:
47    virtual ~Client() {}
48    // Called on the UI thread.
49    virtual void PostMessageFromNativeProcess(int port_id,
50                                              const std::string& message) = 0;
51    virtual void CloseChannel(int port_id,
52                              const std::string& error_message) = 0;
53  };
54
55  // Result returned from IsHostAllowed().
56  enum PolicyPermission {
57    DISALLOW,           // The host is not allowed.
58    ALLOW_SYSTEM_ONLY,  // Allowed only when installed on system level.
59    ALLOW_ALL,          // Allowed when installed on system or user level.
60  };
61
62  virtual ~NativeMessageProcessHost();
63
64  // Returns policy permissions for the host with the specified name.
65  static PolicyPermission IsHostAllowed(const PrefService* pref_service,
66                                        const std::string& native_host_name);
67
68  static scoped_ptr<NativeMessageProcessHost> Create(
69      gfx::NativeView native_view,
70      base::WeakPtr<Client> weak_client_ui,
71      const std::string& source_extension_id,
72      const std::string& native_host_name,
73      int destination_port,
74      bool allow_user_level);
75
76  // Create using specified |launcher|. Used in tests.
77  static scoped_ptr<NativeMessageProcessHost> CreateWithLauncher(
78      base::WeakPtr<Client> weak_client_ui,
79      const std::string& source_extension_id,
80      const std::string& native_host_name,
81      int destination_port,
82      scoped_ptr<NativeProcessLauncher> launcher);
83
84  // Send a message with the specified payload.
85  void Send(const std::string& json);
86
87#if defined(OS_POSIX)
88  // MessageLoopForIO::Watcher interface
89  virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE;
90  virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE;
91#endif  // !defined(OS_POSIX)
92
93  // Try and read a single message from |read_file_|. This should only be called
94  // in unittests when you know there is data in the file.
95  void ReadNowForTesting();
96
97 private:
98  NativeMessageProcessHost(base::WeakPtr<Client> weak_client_ui,
99                           const std::string& source_extension_id,
100                           const std::string& native_host_name,
101                           int destination_port,
102                           scoped_ptr<NativeProcessLauncher> launcher);
103
104  // Starts the host process.
105  void LaunchHostProcess();
106
107  // Callback for NativeProcessLauncher::Launch().
108  void OnHostProcessLaunched(NativeProcessLauncher::LaunchResult result,
109                             base::ProcessHandle process_handle,
110                             base::File read_file,
111                             base::File write_file);
112
113  // Helper methods to read incoming messages.
114  void WaitRead();
115  void DoRead();
116  void OnRead(int result);
117  void HandleReadResult(int result);
118  void ProcessIncomingData(const char* data, int data_size);
119
120  // Helper methods to write outgoing messages.
121  void DoWrite();
122  void HandleWriteResult(int result);
123  void OnWritten(int result);
124
125  // Closes the connection. Called from OnError() and destructor.
126  void Close(const std::string& error_message);
127
128  // The Client messages will be posted to. Should only be accessed from the
129  // UI thread.
130  base::WeakPtr<Client> weak_client_ui_;
131
132  // ID of the calling extension.
133  std::string source_extension_id_;
134
135  // Name of the native messaging host.
136  std::string native_host_name_;
137
138  // The id of the port on the other side of this connection. This is passed to
139  // |weak_client_ui_| when posting messages.
140  int destination_port_;
141
142  // Launcher used to launch the native process.
143  scoped_ptr<NativeProcessLauncher> launcher_;
144
145  // Set to true after the native messaging connection has been stopped, e.g.
146  // due to an error.
147  bool closed_;
148
149  base::ProcessHandle process_handle_;
150
151  // Input stream reader.
152  scoped_ptr<net::FileStream> read_stream_;
153
154#if defined(OS_POSIX)
155  base::PlatformFile read_file_;
156  base::MessageLoopForIO::FileDescriptorWatcher read_watcher_;
157#endif  // !defined(OS_POSIX)
158
159  // Write stream.
160  scoped_ptr<net::FileStream> write_stream_;
161
162  // Read buffer passed to FileStream::Read().
163  scoped_refptr<net::IOBuffer> read_buffer_;
164
165  // Set to true when a read is pending.
166  bool read_pending_;
167
168  // Buffer for incomplete incoming messages.
169  std::string incoming_data_;
170
171  // Queue for outgoing messages.
172  std::queue<scoped_refptr<net::IOBufferWithSize> > write_queue_;
173
174  // The message that's currently being sent.
175  scoped_refptr<net::DrainableIOBuffer> current_write_buffer_;
176
177  // Set to true when a write is pending.
178  bool write_pending_;
179
180  DISALLOW_COPY_AND_ASSIGN(NativeMessageProcessHost);
181};
182
183}  // namespace extensions
184
185#endif  // CHROME_BROWSER_EXTENSIONS_API_MESSAGING_NATIVE_MESSAGE_PROCESS_HOST_H_
186