summaryrefslogtreecommitdiffstats
path: root/chrome/browser/extensions/extension_message_service.h
blob: 29990a99db45a20e6b7a1a407778326c19044e76 (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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
// Copyright (c) 2009 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 CHROME_BROWSER_EXTENSIONS_EXTENSION_MESSAGE_SERVICE_H_
#define CHROME_BROWSER_EXTENSIONS_EXTENSION_MESSAGE_SERVICE_H_

#include <map>
#include <set>
#include <string>

#include "base/lock.h"
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/common/notification_observer.h"

class MessageLoop;
class RenderProcessHost;
class ResourceMessageFilter;
class URLRequestContext;

// This class manages message passing between renderer processes.  It maintains
// a list of available extensions and which renderers each lives in, as well as
// a set of open channels.
//
// Terminology:
// channel: connection between two ports (one of which belongs to an extension)
// port: an IPC::Message::Sender interface through which we communicate to a
//   process.  We use MessageFilters for this since that allows us to send our
//   messages on the IO thread.
class ExtensionMessageService : public NotificationObserver {
 public:
  // Returns the message service for the given context.  Messages can only
  // be sent within a single context.
  static ExtensionMessageService* GetInstance(URLRequestContext* context);

  ExtensionMessageService();

  // --- UI thread only:

  // Gets the process for the specified extension.
  RenderProcessHost* GetProcessForExtension(const std::string& extension_id);

  // Register an extension and its corresponding renderer process.
  void RegisterExtension(const std::string& extension_id,
                         int render_process_id);

  // Add or remove |render_process_pid| as a listener for |event_name|.
  void AddEventListener(std::string event_name, int render_process_id);
  void RemoveEventListener(std::string event_name, int render_process_id);

  // Closes an extension channel for test automation.
  void CloseAutomationChannel(int port_id);

  // Sends a message from a renderer to the given port.
  // TODO(mpcomplete): include the source tab.
  void PostMessageFromRenderer(int port_id, const std::string& message);

  // Send an event to every registered extension renderer.
  void DispatchEventToRenderers(
      const std::string& event_name, const std::string& event_args);

  // NotificationObserver interface.
  void Observe(NotificationType type,
               const NotificationSource& source,
               const NotificationDetails& details);

  // Given an extension's ID, opens a channel between the given automation
  // "port" and that extension.  Returns a channel ID to be used for posting
  // messages between the processes, or -1 if the extension doesn't exist.
  int OpenAutomationChannelToExtension(int source_process_id,
                                       int routing_id,
                                       const std::string& extension_id,
                                       IPC::Message::Sender* source);

  // --- IO thread only:

  // Given an extension's ID, opens a channel between the given renderer "port"
  // and that extension.  Returns a channel ID to be used for posting messages
  // between the processes, or -1 if the extension doesn't exist.
  // This runs on the IO thread so that it can be used in a synchronous IPC
  // message.
  int OpenChannelToExtension(int routing_id, const std::string& extension_id,
                             ResourceMessageFilter* source);

 private:
  // Allocates a pair of port ids.
  // NOTE: this can be called from any thread.
  void AllocatePortIdPair(int* port1, int* port2);

  // Gets the process ID for the specified extension.
  // NOTE: this can be called from any thread.
  int GetProcessIdForExtension(const std::string& extension_id);

  int OpenChannelToExtensionImpl(const std::string& extension_id,
                                 IPC::Message::Sender* source);

  // The UI message loop, used for posting tasks.
  MessageLoop* ui_loop_;

  // A map of extension ID to the render_process_id that the extension lives in.
  typedef std::map<std::string, int> ProcessIDMap;
  ProcessIDMap process_ids_;

  // Protects the process_ids map, since it can be accessed on the IO thread
  // or UI thread.  Be careful not to hold this lock when calling external
  // code (especially sending messages) to avoid deadlock.
  Lock process_ids_lock_;

  // A map between an event name and a set of process id's that are listening
  // to that event.
  typedef std::map<std::string, std::set<int> > ListenerMap;
  ListenerMap listeners_;

  // --- UI thread only:

  // UI-thread specific initialization.  Does nothing if called more than once.
  void Init();

  // Handles channel creation and notifies the destination that a channel was
  // opened.
  void OpenChannelOnUIThread(int source_routing_id,
      int source_port_id, int source_process_id,
      int dest_port_id, int dest_process_id);

  // Common between OpenChannelOnUIThread and
  // OpenAutomationChannelToExtension.
  void OpenChannelOnUIThreadImpl(
    int source_routing_id, int source_port_id, IPC::Message::Sender* source,
    int dest_port_id, int dest_process_id, int source_process_id);

  // The connection between two ports.  It is possible that both ports
  // refer to the same renderer.
  struct MessageChannel {
    IPC::Message::Sender* port1;
    IPC::Message::Sender* port2;
  };

  // A map of channel ID to its channel object.
  typedef std::map<int, MessageChannel> MessageChannelMap;
  MessageChannelMap channels_;

  // True if Init has been called.
  bool initialized_;

  // For generating unique channel IDs.
  int next_port_id_;

  // Protects the next_port_id_ variable, since it can be
  // used on the IO thread or the UI thread.
  Lock next_port_id_lock_;

  DISALLOW_COPY_AND_ASSIGN(ExtensionMessageService);
};

#endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_MESSAGE_SERVICE_H_