OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/extensions/extension_message_service.h" | 5 #include "chrome/browser/extensions/message_service.h" |
6 | 6 |
7 #include "base/atomic_sequence_num.h" | 7 #include "base/atomic_sequence_num.h" |
8 #include "base/bind.h" | 8 #include "base/bind.h" |
9 #include "base/callback.h" | 9 #include "base/callback.h" |
10 #include "base/json/json_writer.h" | 10 #include "base/json/json_writer.h" |
11 #include "base/stl_util.h" | 11 #include "base/stl_util.h" |
12 #include "base/values.h" | 12 #include "base/values.h" |
13 #include "chrome/browser/extensions/extension_host.h" | 13 #include "chrome/browser/extensions/extension_host.h" |
14 #include "chrome/browser/extensions/extension_process_manager.h" | 14 #include "chrome/browser/extensions/extension_process_manager.h" |
15 #include "chrome/browser/extensions/extension_service.h" | 15 #include "chrome/browser/extensions/extension_service.h" |
(...skipping 22 matching lines...) Expand all Loading... |
38 #define GET_CHANNEL_ID(port_id) ((port_id) / 2) | 38 #define GET_CHANNEL_ID(port_id) ((port_id) / 2) |
39 #define GET_CHANNEL_OPENER_ID(channel_id) ((channel_id) * 2) | 39 #define GET_CHANNEL_OPENER_ID(channel_id) ((channel_id) * 2) |
40 #define GET_CHANNEL_RECEIVERS_ID(channel_id) ((channel_id) * 2 + 1) | 40 #define GET_CHANNEL_RECEIVERS_ID(channel_id) ((channel_id) * 2 + 1) |
41 | 41 |
42 // Port1 is always even, port2 is always odd. | 42 // Port1 is always even, port2 is always odd. |
43 #define IS_OPENER_PORT_ID(port_id) (((port_id) & 1) == 0) | 43 #define IS_OPENER_PORT_ID(port_id) (((port_id) & 1) == 0) |
44 | 44 |
45 // Change even to odd and vice versa, to get the other side of a given channel. | 45 // Change even to odd and vice versa, to get the other side of a given channel. |
46 #define GET_OPPOSITE_PORT_ID(source_port_id) ((source_port_id) ^ 1) | 46 #define GET_OPPOSITE_PORT_ID(source_port_id) ((source_port_id) ^ 1) |
47 | 47 |
48 struct ExtensionMessageService::MessagePort { | 48 namespace extensions { |
| 49 |
| 50 struct MessageService::MessagePort { |
49 content::RenderProcessHost* process; | 51 content::RenderProcessHost* process; |
50 int routing_id; | 52 int routing_id; |
51 std::string extension_id; | 53 std::string extension_id; |
52 void* background_host_ptr; // used in IncrementLazyKeepaliveCount | 54 void* background_host_ptr; // used in IncrementLazyKeepaliveCount |
53 | 55 |
54 MessagePort() | 56 MessagePort() |
55 : process(NULL), | 57 : process(NULL), |
56 routing_id(MSG_ROUTING_CONTROL), | 58 routing_id(MSG_ROUTING_CONTROL), |
57 background_host_ptr(NULL) {} | 59 background_host_ptr(NULL) {} |
58 MessagePort(content::RenderProcessHost* process, | 60 MessagePort(content::RenderProcessHost* process, |
59 int routing_id, | 61 int routing_id, |
60 const std::string& extension_id) | 62 const std::string& extension_id) |
61 : process(process), | 63 : process(process), |
62 routing_id(routing_id), | 64 routing_id(routing_id), |
63 extension_id(extension_id), | 65 extension_id(extension_id), |
64 background_host_ptr(NULL) {} | 66 background_host_ptr(NULL) {} |
65 }; | 67 }; |
66 | 68 |
67 struct ExtensionMessageService::MessageChannel { | 69 struct MessageService::MessageChannel { |
68 ExtensionMessageService::MessagePort opener; | 70 MessageService::MessagePort opener; |
69 ExtensionMessageService::MessagePort receiver; | 71 MessageService::MessagePort receiver; |
70 }; | 72 }; |
71 | 73 |
72 struct ExtensionMessageService::OpenChannelParams { | 74 struct MessageService::OpenChannelParams { |
73 content::RenderProcessHost* source; | 75 content::RenderProcessHost* source; |
74 std::string tab_json; | 76 std::string tab_json; |
75 MessagePort receiver; | 77 MessagePort receiver; |
76 int receiver_port_id; | 78 int receiver_port_id; |
77 std::string source_extension_id; | 79 std::string source_extension_id; |
78 std::string target_extension_id; | 80 std::string target_extension_id; |
79 std::string channel_name; | 81 std::string channel_name; |
80 | 82 |
81 OpenChannelParams(content::RenderProcessHost* source, | 83 OpenChannelParams(content::RenderProcessHost* source, |
82 const std::string& tab_json, | 84 const std::string& tab_json, |
83 const MessagePort& receiver, | 85 const MessagePort& receiver, |
84 int receiver_port_id, | 86 int receiver_port_id, |
85 const std::string& source_extension_id, | 87 const std::string& source_extension_id, |
86 const std::string& target_extension_id, | 88 const std::string& target_extension_id, |
87 const std::string& channel_name) | 89 const std::string& channel_name) |
88 : source(source), | 90 : source(source), |
89 tab_json(tab_json), | 91 tab_json(tab_json), |
90 receiver(receiver), | 92 receiver(receiver), |
91 receiver_port_id(receiver_port_id), | 93 receiver_port_id(receiver_port_id), |
92 source_extension_id(source_extension_id), | 94 source_extension_id(source_extension_id), |
93 target_extension_id(target_extension_id), | 95 target_extension_id(target_extension_id), |
94 channel_name(channel_name) {} | 96 channel_name(channel_name) {} |
95 }; | 97 }; |
96 | 98 |
97 namespace { | 99 namespace { |
98 | 100 |
99 static base::StaticAtomicSequenceNumber g_next_channel_id; | 101 static base::StaticAtomicSequenceNumber g_next_channel_id; |
100 | 102 |
101 static void DispatchOnConnect(const ExtensionMessageService::MessagePort& port, | 103 static void DispatchOnConnect(const MessageService::MessagePort& port, |
102 int dest_port_id, | 104 int dest_port_id, |
103 const std::string& channel_name, | 105 const std::string& channel_name, |
104 const std::string& tab_json, | 106 const std::string& tab_json, |
105 const std::string& source_extension_id, | 107 const std::string& source_extension_id, |
106 const std::string& target_extension_id) { | 108 const std::string& target_extension_id) { |
107 port.process->Send(new ExtensionMsg_DispatchOnConnect( | 109 port.process->Send(new ExtensionMsg_DispatchOnConnect( |
108 port.routing_id, dest_port_id, channel_name, | 110 port.routing_id, dest_port_id, channel_name, |
109 tab_json, source_extension_id, target_extension_id)); | 111 tab_json, source_extension_id, target_extension_id)); |
110 } | 112 } |
111 | 113 |
112 static void DispatchOnDisconnect( | 114 static void DispatchOnDisconnect(const MessageService::MessagePort& port, |
113 const ExtensionMessageService::MessagePort& port, int source_port_id, | 115 int source_port_id, |
114 bool connection_error) { | 116 bool connection_error) { |
115 port.process->Send(new ExtensionMsg_DispatchOnDisconnect( | 117 port.process->Send(new ExtensionMsg_DispatchOnDisconnect( |
116 port.routing_id, source_port_id, connection_error)); | 118 port.routing_id, source_port_id, connection_error)); |
117 } | 119 } |
118 | 120 |
119 static void DispatchOnMessage(const ExtensionMessageService::MessagePort& port, | 121 static void DispatchOnMessage(const MessageService::MessagePort& port, |
120 const std::string& message, int target_port_id) { | 122 const std::string& message, |
| 123 int target_port_id) { |
121 port.process->Send(new ExtensionMsg_DeliverMessage( | 124 port.process->Send(new ExtensionMsg_DeliverMessage( |
122 port.routing_id, target_port_id, message)); | 125 port.routing_id, target_port_id, message)); |
123 } | 126 } |
124 | 127 |
125 static content::RenderProcessHost* GetExtensionProcess( | 128 static content::RenderProcessHost* GetExtensionProcess( |
126 Profile* profile, const std::string& extension_id) { | 129 Profile* profile, const std::string& extension_id) { |
127 SiteInstance* site_instance = | 130 SiteInstance* site_instance = |
128 profile->GetExtensionProcessManager()->GetSiteInstanceForURL( | 131 profile->GetExtensionProcessManager()->GetSiteInstanceForURL( |
129 extensions::Extension::GetBaseURLFromExtensionId(extension_id)); | 132 Extension::GetBaseURLFromExtensionId(extension_id)); |
130 | 133 |
131 if (!site_instance->HasProcess()) | 134 if (!site_instance->HasProcess()) |
132 return NULL; | 135 return NULL; |
133 | 136 |
134 return site_instance->GetProcess(); | 137 return site_instance->GetProcess(); |
135 } | 138 } |
136 | 139 |
137 static void IncrementLazyKeepaliveCount( | 140 static void IncrementLazyKeepaliveCount(MessageService::MessagePort* port) { |
138 ExtensionMessageService::MessagePort* port) { | |
139 Profile* profile = | 141 Profile* profile = |
140 Profile::FromBrowserContext(port->process->GetBrowserContext()); | 142 Profile::FromBrowserContext(port->process->GetBrowserContext()); |
141 ExtensionProcessManager* pm = | 143 ExtensionProcessManager* pm = |
142 extensions::ExtensionSystem::Get(profile)->process_manager(); | 144 ExtensionSystem::Get(profile)->process_manager(); |
143 ExtensionHost* host = pm->GetBackgroundHostForExtension(port->extension_id); | 145 ExtensionHost* host = pm->GetBackgroundHostForExtension(port->extension_id); |
144 if (host && host->extension()->has_lazy_background_page()) | 146 if (host && host->extension()->has_lazy_background_page()) |
145 pm->IncrementLazyKeepaliveCount(host->extension()); | 147 pm->IncrementLazyKeepaliveCount(host->extension()); |
146 | 148 |
147 // Keep track of the background host, so when we decrement, we only do so if | 149 // Keep track of the background host, so when we decrement, we only do so if |
148 // the host hasn't reloaded. | 150 // the host hasn't reloaded. |
149 port->background_host_ptr = host; | 151 port->background_host_ptr = host; |
150 } | 152 } |
151 | 153 |
152 static void DecrementLazyKeepaliveCount( | 154 static void DecrementLazyKeepaliveCount(MessageService::MessagePort* port) { |
153 ExtensionMessageService::MessagePort* port) { | |
154 Profile* profile = | 155 Profile* profile = |
155 Profile::FromBrowserContext(port->process->GetBrowserContext()); | 156 Profile::FromBrowserContext(port->process->GetBrowserContext()); |
156 ExtensionProcessManager* pm = | 157 ExtensionProcessManager* pm = |
157 extensions::ExtensionSystem::Get(profile)->process_manager(); | 158 ExtensionSystem::Get(profile)->process_manager(); |
158 ExtensionHost* host = pm->GetBackgroundHostForExtension(port->extension_id); | 159 ExtensionHost* host = pm->GetBackgroundHostForExtension(port->extension_id); |
159 if (host && host == port->background_host_ptr) | 160 if (host && host == port->background_host_ptr) |
160 pm->DecrementLazyKeepaliveCount(host->extension()); | 161 pm->DecrementLazyKeepaliveCount(host->extension()); |
161 } | 162 } |
162 | 163 |
163 } // namespace | 164 } // namespace |
164 | 165 |
165 // static | 166 // static |
166 void ExtensionMessageService::AllocatePortIdPair(int* port1, int* port2) { | 167 void MessageService::AllocatePortIdPair(int* port1, int* port2) { |
167 int channel_id = g_next_channel_id.GetNext(); | 168 int channel_id = g_next_channel_id.GetNext(); |
168 int port1_id = channel_id * 2; | 169 int port1_id = channel_id * 2; |
169 int port2_id = channel_id * 2 + 1; | 170 int port2_id = channel_id * 2 + 1; |
170 | 171 |
171 // Sanity checks to make sure our channel<->port converters are correct. | 172 // Sanity checks to make sure our channel<->port converters are correct. |
172 DCHECK(IS_OPENER_PORT_ID(port1_id)); | 173 DCHECK(IS_OPENER_PORT_ID(port1_id)); |
173 DCHECK(GET_OPPOSITE_PORT_ID(port1_id) == port2_id); | 174 DCHECK(GET_OPPOSITE_PORT_ID(port1_id) == port2_id); |
174 DCHECK(GET_OPPOSITE_PORT_ID(port2_id) == port1_id); | 175 DCHECK(GET_OPPOSITE_PORT_ID(port2_id) == port1_id); |
175 DCHECK(GET_CHANNEL_ID(port1_id) == GET_CHANNEL_ID(port2_id)); | 176 DCHECK(GET_CHANNEL_ID(port1_id) == GET_CHANNEL_ID(port2_id)); |
176 DCHECK(GET_CHANNEL_ID(port1_id) == channel_id); | 177 DCHECK(GET_CHANNEL_ID(port1_id) == channel_id); |
177 DCHECK(GET_CHANNEL_OPENER_ID(channel_id) == port1_id); | 178 DCHECK(GET_CHANNEL_OPENER_ID(channel_id) == port1_id); |
178 DCHECK(GET_CHANNEL_RECEIVERS_ID(channel_id) == port2_id); | 179 DCHECK(GET_CHANNEL_RECEIVERS_ID(channel_id) == port2_id); |
179 | 180 |
180 *port1 = port1_id; | 181 *port1 = port1_id; |
181 *port2 = port2_id; | 182 *port2 = port2_id; |
182 } | 183 } |
183 | 184 |
184 ExtensionMessageService::ExtensionMessageService( | 185 MessageService::MessageService( |
185 extensions::LazyBackgroundTaskQueue* queue) | 186 LazyBackgroundTaskQueue* queue) |
186 : lazy_background_task_queue_(queue) { | 187 : lazy_background_task_queue_(queue) { |
187 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, | 188 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
188 content::NotificationService::AllBrowserContextsAndSources()); | 189 content::NotificationService::AllBrowserContextsAndSources()); |
189 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, | 190 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, |
190 content::NotificationService::AllBrowserContextsAndSources()); | 191 content::NotificationService::AllBrowserContextsAndSources()); |
191 } | 192 } |
192 | 193 |
193 ExtensionMessageService::~ExtensionMessageService() { | 194 MessageService::~MessageService() { |
194 STLDeleteContainerPairSecondPointers(channels_.begin(), channels_.end()); | 195 STLDeleteContainerPairSecondPointers(channels_.begin(), channels_.end()); |
195 channels_.clear(); | 196 channels_.clear(); |
196 } | 197 } |
197 | 198 |
198 void ExtensionMessageService::OpenChannelToExtension( | 199 void MessageService::OpenChannelToExtension( |
199 int source_process_id, int source_routing_id, int receiver_port_id, | 200 int source_process_id, int source_routing_id, int receiver_port_id, |
200 const std::string& source_extension_id, | 201 const std::string& source_extension_id, |
201 const std::string& target_extension_id, | 202 const std::string& target_extension_id, |
202 const std::string& channel_name) { | 203 const std::string& channel_name) { |
203 content::RenderProcessHost* source = | 204 content::RenderProcessHost* source = |
204 content::RenderProcessHost::FromID(source_process_id); | 205 content::RenderProcessHost::FromID(source_process_id); |
205 if (!source) | 206 if (!source) |
206 return; | 207 return; |
207 Profile* profile = Profile::FromBrowserContext(source->GetBrowserContext()); | 208 Profile* profile = Profile::FromBrowserContext(source->GetBrowserContext()); |
208 | 209 |
209 // Note: we use the source's profile here. If the source is an incognito | 210 // Note: we use the source's profile here. If the source is an incognito |
210 // process, we will use the incognito EPM to find the right extension process, | 211 // process, we will use the incognito EPM to find the right extension process, |
211 // which depends on whether the extension uses spanning or split mode. | 212 // which depends on whether the extension uses spanning or split mode. |
212 MessagePort receiver( | 213 MessagePort receiver(GetExtensionProcess(profile, target_extension_id), |
213 GetExtensionProcess(profile, target_extension_id), | 214 MSG_ROUTING_CONTROL, |
214 MSG_ROUTING_CONTROL, | 215 target_extension_id); |
215 target_extension_id); | |
216 WebContents* source_contents = tab_util::GetWebContentsByID( | 216 WebContents* source_contents = tab_util::GetWebContentsByID( |
217 source_process_id, source_routing_id); | 217 source_process_id, source_routing_id); |
218 | 218 |
219 // Include info about the opener's tab (if it was a tab). | 219 // Include info about the opener's tab (if it was a tab). |
220 std::string tab_json = "null"; | 220 std::string tab_json = "null"; |
221 if (source_contents) { | 221 if (source_contents) { |
222 scoped_ptr<DictionaryValue> tab_value( | 222 scoped_ptr<DictionaryValue> tab_value( |
223 ExtensionTabUtil::CreateTabValue(source_contents)); | 223 ExtensionTabUtil::CreateTabValue(source_contents)); |
224 base::JSONWriter::Write(tab_value.get(), &tab_json); | 224 base::JSONWriter::Write(tab_value.get(), &tab_json); |
225 } | 225 } |
226 | 226 |
227 OpenChannelParams params(source, tab_json, receiver, receiver_port_id, | 227 OpenChannelParams params(source, tab_json, receiver, receiver_port_id, |
228 source_extension_id, target_extension_id, | 228 source_extension_id, target_extension_id, |
229 channel_name); | 229 channel_name); |
230 | 230 |
231 // The target might be a lazy background page. In that case, we have to check | 231 // The target might be a lazy background page. In that case, we have to check |
232 // if it is loaded and ready, and if not, queue up the task and load the | 232 // if it is loaded and ready, and if not, queue up the task and load the |
233 // page. | 233 // page. |
234 if (MaybeAddPendingOpenChannelTask(profile, params)) | 234 if (MaybeAddPendingOpenChannelTask(profile, params)) |
235 return; | 235 return; |
236 | 236 |
237 OpenChannelImpl(params); | 237 OpenChannelImpl(params); |
238 } | 238 } |
239 | 239 |
240 void ExtensionMessageService::OpenChannelToTab( | 240 void MessageService::OpenChannelToTab( |
241 int source_process_id, int source_routing_id, int receiver_port_id, | 241 int source_process_id, int source_routing_id, int receiver_port_id, |
242 int tab_id, const std::string& extension_id, | 242 int tab_id, const std::string& extension_id, |
243 const std::string& channel_name) { | 243 const std::string& channel_name) { |
244 content::RenderProcessHost* source = | 244 content::RenderProcessHost* source = |
245 content::RenderProcessHost::FromID(source_process_id); | 245 content::RenderProcessHost::FromID(source_process_id); |
246 if (!source) | 246 if (!source) |
247 return; | 247 return; |
248 Profile* profile = Profile::FromBrowserContext(source->GetBrowserContext()); | 248 Profile* profile = Profile::FromBrowserContext(source->GetBrowserContext()); |
249 | 249 |
250 TabContents* contents = NULL; | 250 TabContents* contents = NULL; |
(...skipping 23 matching lines...) Expand all Loading... |
274 scoped_ptr<DictionaryValue> tab_value( | 274 scoped_ptr<DictionaryValue> tab_value( |
275 ExtensionTabUtil::CreateTabValue(source_contents)); | 275 ExtensionTabUtil::CreateTabValue(source_contents)); |
276 base::JSONWriter::Write(tab_value.get(), &tab_json); | 276 base::JSONWriter::Write(tab_value.get(), &tab_json); |
277 } | 277 } |
278 | 278 |
279 OpenChannelParams params(source, tab_json, receiver, receiver_port_id, | 279 OpenChannelParams params(source, tab_json, receiver, receiver_port_id, |
280 extension_id, extension_id, channel_name); | 280 extension_id, extension_id, channel_name); |
281 OpenChannelImpl(params); | 281 OpenChannelImpl(params); |
282 } | 282 } |
283 | 283 |
284 bool ExtensionMessageService::OpenChannelImpl(const OpenChannelParams& params) { | 284 bool MessageService::OpenChannelImpl(const OpenChannelParams& params) { |
285 if (!params.source) | 285 if (!params.source) |
286 return false; // Closed while in flight. | 286 return false; // Closed while in flight. |
287 | 287 |
288 if (!params.receiver.process) { | 288 if (!params.receiver.process) { |
289 // Treat it as a disconnect. | 289 // Treat it as a disconnect. |
290 DispatchOnDisconnect(MessagePort(params.source, MSG_ROUTING_CONTROL, ""), | 290 DispatchOnDisconnect(MessagePort(params.source, MSG_ROUTING_CONTROL, ""), |
291 GET_OPPOSITE_PORT_ID(params.receiver_port_id), true); | 291 GET_OPPOSITE_PORT_ID(params.receiver_port_id), true); |
292 return false; | 292 return false; |
293 } | 293 } |
294 | 294 |
(...skipping 20 matching lines...) Expand all Loading... |
315 DispatchOnConnect(params.receiver, params.receiver_port_id, | 315 DispatchOnConnect(params.receiver, params.receiver_port_id, |
316 params.channel_name, params.tab_json, | 316 params.channel_name, params.tab_json, |
317 params.source_extension_id, params.target_extension_id); | 317 params.source_extension_id, params.target_extension_id); |
318 | 318 |
319 // Keep both ends of the channel alive until the channel is closed. | 319 // Keep both ends of the channel alive until the channel is closed. |
320 IncrementLazyKeepaliveCount(&channel->opener); | 320 IncrementLazyKeepaliveCount(&channel->opener); |
321 IncrementLazyKeepaliveCount(&channel->receiver); | 321 IncrementLazyKeepaliveCount(&channel->receiver); |
322 return true; | 322 return true; |
323 } | 323 } |
324 | 324 |
325 void ExtensionMessageService::CloseChannel(int port_id, bool connection_error) { | 325 void MessageService::CloseChannel(int port_id, bool connection_error) { |
326 // Note: The channel might be gone already, if the other side closed first. | 326 // Note: The channel might be gone already, if the other side closed first. |
327 int channel_id = GET_CHANNEL_ID(port_id); | 327 int channel_id = GET_CHANNEL_ID(port_id); |
328 MessageChannelMap::iterator it = channels_.find(channel_id); | 328 MessageChannelMap::iterator it = channels_.find(channel_id); |
329 if (it == channels_.end()) { | 329 if (it == channels_.end()) { |
330 PendingChannelMap::iterator pending = pending_channels_.find(channel_id); | 330 PendingChannelMap::iterator pending = pending_channels_.find(channel_id); |
331 if (pending != pending_channels_.end()) { | 331 if (pending != pending_channels_.end()) { |
332 lazy_background_task_queue_->AddPendingTask( | 332 lazy_background_task_queue_->AddPendingTask( |
333 pending->second.first, pending->second.second, | 333 pending->second.first, pending->second.second, |
334 base::Bind(&ExtensionMessageService::PendingCloseChannel, | 334 base::Bind(&MessageService::PendingCloseChannel, |
335 base::Unretained(this), port_id, connection_error)); | 335 base::Unretained(this), port_id, connection_error)); |
336 } | 336 } |
337 return; | 337 return; |
338 } | 338 } |
339 CloseChannelImpl(it, port_id, connection_error, true); | 339 CloseChannelImpl(it, port_id, connection_error, true); |
340 } | 340 } |
341 | 341 |
342 void ExtensionMessageService::CloseChannelImpl( | 342 void MessageService::CloseChannelImpl( |
343 MessageChannelMap::iterator channel_iter, int closing_port_id, | 343 MessageChannelMap::iterator channel_iter, int closing_port_id, |
344 bool connection_error, bool notify_other_port) { | 344 bool connection_error, bool notify_other_port) { |
345 MessageChannel* channel = channel_iter->second; | 345 MessageChannel* channel = channel_iter->second; |
346 | 346 |
347 // Notify the other side. | 347 // Notify the other side. |
348 if (notify_other_port) { | 348 if (notify_other_port) { |
349 const MessagePort& port = IS_OPENER_PORT_ID(closing_port_id) ? | 349 const MessagePort& port = IS_OPENER_PORT_ID(closing_port_id) ? |
350 channel->receiver : channel->opener; | 350 channel->receiver : channel->opener; |
351 DispatchOnDisconnect(port, GET_OPPOSITE_PORT_ID(closing_port_id), | 351 DispatchOnDisconnect(port, GET_OPPOSITE_PORT_ID(closing_port_id), |
352 connection_error); | 352 connection_error); |
353 } | 353 } |
354 | 354 |
355 // Balance the addrefs in OpenChannelImpl. | 355 // Balance the addrefs in OpenChannelImpl. |
356 DecrementLazyKeepaliveCount(&channel->opener); | 356 DecrementLazyKeepaliveCount(&channel->opener); |
357 DecrementLazyKeepaliveCount(&channel->receiver); | 357 DecrementLazyKeepaliveCount(&channel->receiver); |
358 | 358 |
359 delete channel_iter->second; | 359 delete channel_iter->second; |
360 channels_.erase(channel_iter); | 360 channels_.erase(channel_iter); |
361 } | 361 } |
362 | 362 |
363 void ExtensionMessageService::PostMessageFromRenderer( | 363 void MessageService::PostMessageFromRenderer( |
364 int source_port_id, const std::string& message) { | 364 int source_port_id, const std::string& message) { |
365 int channel_id = GET_CHANNEL_ID(source_port_id); | 365 int channel_id = GET_CHANNEL_ID(source_port_id); |
366 MessageChannelMap::iterator iter = channels_.find(channel_id); | 366 MessageChannelMap::iterator iter = channels_.find(channel_id); |
367 if (iter == channels_.end()) { | 367 if (iter == channels_.end()) { |
368 // If this channel is pending, queue up the PostMessage to run once | 368 // If this channel is pending, queue up the PostMessage to run once |
369 // the channel opens. | 369 // the channel opens. |
370 PendingChannelMap::iterator pending = pending_channels_.find(channel_id); | 370 PendingChannelMap::iterator pending = pending_channels_.find(channel_id); |
371 if (pending != pending_channels_.end()) { | 371 if (pending != pending_channels_.end()) { |
372 lazy_background_task_queue_->AddPendingTask( | 372 lazy_background_task_queue_->AddPendingTask( |
373 pending->second.first, pending->second.second, | 373 pending->second.first, pending->second.second, |
374 base::Bind(&ExtensionMessageService::PendingPostMessage, | 374 base::Bind(&MessageService::PendingPostMessage, |
375 base::Unretained(this), source_port_id, message)); | 375 base::Unretained(this), source_port_id, message)); |
376 } | 376 } |
377 return; | 377 return; |
378 } | 378 } |
379 | 379 |
380 // Figure out which port the ID corresponds to. | 380 // Figure out which port the ID corresponds to. |
381 int dest_port_id = GET_OPPOSITE_PORT_ID(source_port_id); | 381 int dest_port_id = GET_OPPOSITE_PORT_ID(source_port_id); |
382 const MessagePort& port = IS_OPENER_PORT_ID(dest_port_id) ? | 382 const MessagePort& port = IS_OPENER_PORT_ID(dest_port_id) ? |
383 iter->second->opener : iter->second->receiver; | 383 iter->second->opener : iter->second->receiver; |
384 | 384 |
385 DispatchOnMessage(port, message, dest_port_id); | 385 DispatchOnMessage(port, message, dest_port_id); |
386 } | 386 } |
387 | 387 |
388 void ExtensionMessageService::Observe( | 388 void MessageService::Observe(int type, |
389 int type, | 389 const content::NotificationSource& source, |
390 const content::NotificationSource& source, | 390 const content::NotificationDetails& details) { |
391 const content::NotificationDetails& details) { | |
392 switch (type) { | 391 switch (type) { |
393 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: | 392 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: |
394 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: { | 393 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: { |
395 content::RenderProcessHost* renderer = | 394 content::RenderProcessHost* renderer = |
396 content::Source<content::RenderProcessHost>(source).ptr(); | 395 content::Source<content::RenderProcessHost>(source).ptr(); |
397 OnProcessClosed(renderer); | 396 OnProcessClosed(renderer); |
398 break; | 397 break; |
399 } | 398 } |
400 default: | 399 default: |
401 NOTREACHED(); | 400 NOTREACHED(); |
402 return; | 401 return; |
403 } | 402 } |
404 } | 403 } |
405 | 404 |
406 void ExtensionMessageService::OnProcessClosed( | 405 void MessageService::OnProcessClosed(content::RenderProcessHost* process) { |
407 content::RenderProcessHost* process) { | |
408 // Close any channels that share this renderer. We notify the opposite | 406 // Close any channels that share this renderer. We notify the opposite |
409 // port that his pair has closed. | 407 // port that his pair has closed. |
410 for (MessageChannelMap::iterator it = channels_.begin(); | 408 for (MessageChannelMap::iterator it = channels_.begin(); |
411 it != channels_.end(); ) { | 409 it != channels_.end(); ) { |
412 MessageChannelMap::iterator current = it++; | 410 MessageChannelMap::iterator current = it++; |
413 // If both sides are the same renderer, and it is closing, there is no | 411 // If both sides are the same renderer, and it is closing, there is no |
414 // "other" port, so there's no need to notify it. | 412 // "other" port, so there's no need to notify it. |
415 bool notify_other_port = | 413 bool notify_other_port = |
416 current->second->opener.process != current->second->receiver.process; | 414 current->second->opener.process != current->second->receiver.process; |
417 | 415 |
418 if (current->second->opener.process == process) { | 416 if (current->second->opener.process == process) { |
419 CloseChannelImpl(current, GET_CHANNEL_OPENER_ID(current->first), | 417 CloseChannelImpl(current, GET_CHANNEL_OPENER_ID(current->first), |
420 false, notify_other_port); | 418 false, notify_other_port); |
421 } else if (current->second->receiver.process == process) { | 419 } else if (current->second->receiver.process == process) { |
422 CloseChannelImpl(current, GET_CHANNEL_RECEIVERS_ID(current->first), | 420 CloseChannelImpl(current, GET_CHANNEL_RECEIVERS_ID(current->first), |
423 false, notify_other_port); | 421 false, notify_other_port); |
424 } | 422 } |
425 } | 423 } |
426 } | 424 } |
427 | 425 |
428 bool ExtensionMessageService::MaybeAddPendingOpenChannelTask( | 426 bool MessageService::MaybeAddPendingOpenChannelTask( |
429 Profile* profile, | 427 Profile* profile, |
430 const OpenChannelParams& params) { | 428 const OpenChannelParams& params) { |
431 ExtensionService* service = profile->GetExtensionService(); | 429 ExtensionService* service = profile->GetExtensionService(); |
432 const std::string& extension_id = params.target_extension_id; | 430 const std::string& extension_id = params.target_extension_id; |
433 const extensions::Extension* extension = service->extensions()->GetByID( | 431 const Extension* extension = service->extensions()->GetByID( |
434 extension_id); | 432 extension_id); |
435 if (extension && extension->has_lazy_background_page()) { | 433 if (extension && extension->has_lazy_background_page()) { |
436 // If the extension uses spanning incognito mode, make sure we're always | 434 // If the extension uses spanning incognito mode, make sure we're always |
437 // using the original profile since that is what the extension process | 435 // using the original profile since that is what the extension process |
438 // will use. | 436 // will use. |
439 if (!extension->incognito_split_mode()) | 437 if (!extension->incognito_split_mode()) |
440 profile = profile->GetOriginalProfile(); | 438 profile = profile->GetOriginalProfile(); |
441 | 439 |
442 if (lazy_background_task_queue_->ShouldEnqueueTask(profile, extension)) { | 440 if (lazy_background_task_queue_->ShouldEnqueueTask(profile, extension)) { |
443 lazy_background_task_queue_->AddPendingTask(profile, extension_id, | 441 lazy_background_task_queue_->AddPendingTask(profile, extension_id, |
444 base::Bind(&ExtensionMessageService::PendingOpenChannel, | 442 base::Bind(&MessageService::PendingOpenChannel, |
445 base::Unretained(this), params, params.source->GetID())); | 443 base::Unretained(this), params, params.source->GetID())); |
446 pending_channels_[GET_CHANNEL_ID(params.receiver_port_id)] = | 444 pending_channels_[GET_CHANNEL_ID(params.receiver_port_id)] = |
447 PendingChannel(profile, extension_id); | 445 PendingChannel(profile, extension_id); |
448 return true; | 446 return true; |
449 } | 447 } |
450 } | 448 } |
451 | 449 |
452 return false; | 450 return false; |
453 } | 451 } |
454 | 452 |
455 void ExtensionMessageService::PendingOpenChannel( | 453 void MessageService::PendingOpenChannel(const OpenChannelParams& params_in, |
456 const OpenChannelParams& params_in, | 454 int source_process_id, |
457 int source_process_id, | 455 ExtensionHost* host) { |
458 ExtensionHost* host) { | |
459 if (!host) | 456 if (!host) |
460 return; // TODO(mpcomplete): notify source of disconnect? | 457 return; // TODO(mpcomplete): notify source of disconnect? |
461 | 458 |
462 // Re-lookup the source process since it may no longer be valid. | 459 // Re-lookup the source process since it may no longer be valid. |
463 OpenChannelParams params = params_in; | 460 OpenChannelParams params = params_in; |
464 params.source = content::RenderProcessHost::FromID(source_process_id); | 461 params.source = content::RenderProcessHost::FromID(source_process_id); |
465 if (!params.source) | 462 if (!params.source) |
466 return; | 463 return; |
467 | 464 |
468 params.receiver = MessagePort(host->render_process_host(), | 465 params.receiver = MessagePort(host->render_process_host(), |
469 MSG_ROUTING_CONTROL, | 466 MSG_ROUTING_CONTROL, |
470 params.target_extension_id); | 467 params.target_extension_id); |
471 OpenChannelImpl(params); | 468 OpenChannelImpl(params); |
472 } | 469 } |
| 470 |
| 471 } // namespace extensions |
OLD | NEW |