Chromium Code Reviews| 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/api/messaging/message_service.h" | 5 #include "chrome/browser/extensions/api/messaging/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" |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 25 #include "chrome/common/extensions/background_info.h" | 25 #include "chrome/common/extensions/background_info.h" |
| 26 #include "chrome/common/extensions/extension.h" | 26 #include "chrome/common/extensions/extension.h" |
| 27 #include "chrome/common/extensions/extension_messages.h" | 27 #include "chrome/common/extensions/extension_messages.h" |
| 28 #include "chrome/common/extensions/incognito_handler.h" | 28 #include "chrome/common/extensions/incognito_handler.h" |
| 29 #include "content/public/browser/browser_thread.h" | 29 #include "content/public/browser/browser_thread.h" |
| 30 #include "content/public/browser/notification_service.h" | 30 #include "content/public/browser/notification_service.h" |
| 31 #include "content/public/browser/render_process_host.h" | 31 #include "content/public/browser/render_process_host.h" |
| 32 #include "content/public/browser/render_view_host.h" | 32 #include "content/public/browser/render_view_host.h" |
| 33 #include "content/public/browser/site_instance.h" | 33 #include "content/public/browser/site_instance.h" |
| 34 #include "content/public/browser/web_contents.h" | 34 #include "content/public/browser/web_contents.h" |
| 35 #include "googleurl/src/gurl.h" | |
| 35 | 36 |
| 36 using content::SiteInstance; | 37 using content::SiteInstance; |
| 37 using content::WebContents; | 38 using content::WebContents; |
| 38 | 39 |
| 39 // Since we have 2 ports for every channel, we just index channels by half the | 40 // Since we have 2 ports for every channel, we just index channels by half the |
| 40 // port ID. | 41 // port ID. |
| 41 #define GET_CHANNEL_ID(port_id) ((port_id) / 2) | 42 #define GET_CHANNEL_ID(port_id) ((port_id) / 2) |
| 42 #define GET_CHANNEL_OPENER_ID(channel_id) ((channel_id) * 2) | 43 #define GET_CHANNEL_OPENER_ID(channel_id) ((channel_id) * 2) |
| 43 #define GET_CHANNEL_RECEIVERS_ID(channel_id) ((channel_id) * 2 + 1) | 44 #define GET_CHANNEL_RECEIVERS_ID(channel_id) ((channel_id) * 2 + 1) |
| 44 | 45 |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 59 "Native Messaging is not supported on this platform."; | 60 "Native Messaging is not supported on this platform."; |
| 60 } | 61 } |
| 61 | 62 |
| 62 struct MessageService::MessageChannel { | 63 struct MessageService::MessageChannel { |
| 63 scoped_ptr<MessagePort> opener; | 64 scoped_ptr<MessagePort> opener; |
| 64 scoped_ptr<MessagePort> receiver; | 65 scoped_ptr<MessagePort> receiver; |
| 65 }; | 66 }; |
| 66 | 67 |
| 67 struct MessageService::OpenChannelParams { | 68 struct MessageService::OpenChannelParams { |
| 68 content::RenderProcessHost* source; | 69 content::RenderProcessHost* source; |
| 69 std::string tab_json; | 70 DictionaryValue source_tab; |
| 70 scoped_ptr<MessagePort> receiver; | 71 scoped_ptr<MessagePort> receiver; |
| 71 int receiver_port_id; | 72 int receiver_port_id; |
| 72 std::string source_extension_id; | 73 std::string source_extension_id; |
| 73 std::string target_extension_id; | 74 std::string target_extension_id; |
| 75 GURL source_url; | |
| 74 std::string channel_name; | 76 std::string channel_name; |
| 75 | 77 |
| 76 // Takes ownership of receiver. | 78 // Takes ownership of receiver. |
| 77 OpenChannelParams(content::RenderProcessHost* source, | 79 OpenChannelParams(content::RenderProcessHost* source, |
| 78 const std::string& tab_json, | 80 scoped_ptr<DictionaryValue> source_tab, |
| 79 MessagePort* receiver, | 81 MessagePort* receiver, |
| 80 int receiver_port_id, | 82 int receiver_port_id, |
| 81 const std::string& source_extension_id, | 83 const std::string& source_extension_id, |
| 82 const std::string& target_extension_id, | 84 const std::string& target_extension_id, |
| 85 const GURL& source_url, | |
| 83 const std::string& channel_name) | 86 const std::string& channel_name) |
| 84 : source(source), | 87 : source(source), |
| 85 tab_json(tab_json), | |
| 86 receiver(receiver), | 88 receiver(receiver), |
| 87 receiver_port_id(receiver_port_id), | 89 receiver_port_id(receiver_port_id), |
| 88 source_extension_id(source_extension_id), | 90 source_extension_id(source_extension_id), |
| 89 target_extension_id(target_extension_id), | 91 target_extension_id(target_extension_id), |
| 90 channel_name(channel_name) {} | 92 source_url(source_url), |
| 93 channel_name(channel_name) { | |
| 94 if (source_tab) | |
| 95 this->source_tab.Swap(source_tab.get()); | |
| 96 } | |
| 97 | |
| 98 private: | |
| 99 DISALLOW_COPY_AND_ASSIGN(OpenChannelParams); | |
| 91 }; | 100 }; |
| 92 | 101 |
| 93 namespace { | 102 namespace { |
| 94 | 103 |
| 95 static base::StaticAtomicSequenceNumber g_next_channel_id; | 104 static base::StaticAtomicSequenceNumber g_next_channel_id; |
| 96 | 105 |
| 97 static content::RenderProcessHost* GetExtensionProcess( | 106 static content::RenderProcessHost* GetExtensionProcess( |
| 98 Profile* profile, const std::string& extension_id) { | 107 Profile* profile, const std::string& extension_id) { |
| 99 SiteInstance* site_instance = | 108 SiteInstance* site_instance = |
| 100 extensions::ExtensionSystem::Get(profile)->process_manager()-> | 109 extensions::ExtensionSystem::Get(profile)->process_manager()-> |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 145 | 154 |
| 146 MessageService::~MessageService() { | 155 MessageService::~MessageService() { |
| 147 STLDeleteContainerPairSecondPointers(channels_.begin(), channels_.end()); | 156 STLDeleteContainerPairSecondPointers(channels_.begin(), channels_.end()); |
| 148 channels_.clear(); | 157 channels_.clear(); |
| 149 } | 158 } |
| 150 | 159 |
| 151 void MessageService::OpenChannelToExtension( | 160 void MessageService::OpenChannelToExtension( |
| 152 int source_process_id, int source_routing_id, int receiver_port_id, | 161 int source_process_id, int source_routing_id, int receiver_port_id, |
| 153 const std::string& source_extension_id, | 162 const std::string& source_extension_id, |
| 154 const std::string& target_extension_id, | 163 const std::string& target_extension_id, |
| 164 const GURL& source_url, | |
| 155 const std::string& channel_name) { | 165 const std::string& channel_name) { |
| 156 content::RenderProcessHost* source = | 166 content::RenderProcessHost* source = |
| 157 content::RenderProcessHost::FromID(source_process_id); | 167 content::RenderProcessHost::FromID(source_process_id); |
| 158 if (!source) | 168 if (!source) |
| 159 return; | 169 return; |
| 160 Profile* profile = Profile::FromBrowserContext(source->GetBrowserContext()); | 170 Profile* profile = Profile::FromBrowserContext(source->GetBrowserContext()); |
| 161 | 171 |
| 162 // Note: we use the source's profile here. If the source is an incognito | 172 // Note: we use the source's profile here. If the source is an incognito |
| 163 // process, we will use the incognito EPM to find the right extension process, | 173 // process, we will use the incognito EPM to find the right extension process, |
| 164 // which depends on whether the extension uses spanning or split mode. | 174 // which depends on whether the extension uses spanning or split mode. |
| 165 MessagePort* receiver = new ExtensionMessagePort( | 175 MessagePort* receiver = new ExtensionMessagePort( |
| 166 GetExtensionProcess(profile, target_extension_id), MSG_ROUTING_CONTROL, | 176 GetExtensionProcess(profile, target_extension_id), MSG_ROUTING_CONTROL, |
| 167 target_extension_id); | 177 target_extension_id); |
| 168 WebContents* source_contents = tab_util::GetWebContentsByID( | 178 WebContents* source_contents = tab_util::GetWebContentsByID( |
| 169 source_process_id, source_routing_id); | 179 source_process_id, source_routing_id); |
| 170 | 180 |
| 171 // Include info about the opener's tab (if it was a tab). | 181 // Include info about the opener's tab (if it was a tab). |
| 172 std::string tab_json = "null"; | 182 scoped_ptr<DictionaryValue> source_tab; |
| 173 if (source_contents) { | 183 GURL source_url_for_tab; |
| 174 scoped_ptr<DictionaryValue> tab_value(ExtensionTabUtil::CreateTabValue( | 184 |
| 175 source_contents)); | 185 if (source_contents && ExtensionTabUtil::GetTabId(source_contents) >= 0) { |
| 176 base::JSONWriter::Write(tab_value.get(), &tab_json); | 186 source_tab.reset(ExtensionTabUtil::CreateTabValue(source_contents)); |
| 187 source_url_for_tab = source_url; | |
| 177 } | 188 } |
| 178 | 189 |
| 179 OpenChannelParams* params = new OpenChannelParams(source, tab_json, receiver, | 190 OpenChannelParams* params = new OpenChannelParams(source, |
| 191 source_tab.Pass(), | |
| 192 receiver, | |
| 180 receiver_port_id, | 193 receiver_port_id, |
| 181 source_extension_id, | 194 source_extension_id, |
| 182 target_extension_id, | 195 target_extension_id, |
| 196 source_url_for_tab, | |
| 183 channel_name); | 197 channel_name); |
| 184 | 198 |
| 185 // The target might be a lazy background page. In that case, we have to check | 199 // The target might be a lazy background page. In that case, we have to check |
| 186 // if it is loaded and ready, and if not, queue up the task and load the | 200 // if it is loaded and ready, and if not, queue up the task and load the |
| 187 // page. | 201 // page. |
| 188 if (MaybeAddPendingOpenChannelTask(profile, params)) { | 202 if (MaybeAddPendingOpenChannelTask(profile, params)) { |
| 189 return; | 203 return; |
| 190 } | 204 } |
| 191 | 205 |
| 192 OpenChannelImpl(scoped_ptr<OpenChannelParams>(params)); | 206 OpenChannelImpl(make_scoped_ptr(params)); |
| 193 } | 207 } |
| 194 | 208 |
| 195 void MessageService::OpenChannelToNativeApp( | 209 void MessageService::OpenChannelToNativeApp( |
| 196 int source_process_id, | 210 int source_process_id, |
| 197 int source_routing_id, | 211 int source_routing_id, |
| 198 int receiver_port_id, | 212 int receiver_port_id, |
| 199 const std::string& source_extension_id, | 213 const std::string& source_extension_id, |
| 200 const std::string& native_app_name) { | 214 const std::string& native_app_name) { |
| 201 content::RenderProcessHost* source = | 215 content::RenderProcessHost* source = |
| 202 content::RenderProcessHost::FromID(source_process_id); | 216 content::RenderProcessHost::FromID(source_process_id); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 215 APIPermission::kNativeMessaging); | 229 APIPermission::kNativeMessaging); |
| 216 } | 230 } |
| 217 | 231 |
| 218 if (!has_permission) { | 232 if (!has_permission) { |
| 219 ExtensionMessagePort port(source, MSG_ROUTING_CONTROL, std::string()); | 233 ExtensionMessagePort port(source, MSG_ROUTING_CONTROL, std::string()); |
| 220 port.DispatchOnDisconnect(GET_OPPOSITE_PORT_ID(receiver_port_id), | 234 port.DispatchOnDisconnect(GET_OPPOSITE_PORT_ID(receiver_port_id), |
| 221 kMissingPermissionError); | 235 kMissingPermissionError); |
| 222 return; | 236 return; |
| 223 } | 237 } |
| 224 | 238 |
| 225 WebContents* source_contents = tab_util::GetWebContentsByID( | |
| 226 source_process_id, source_routing_id); | |
| 227 | |
| 228 // Include info about the opener's tab (if it was a tab). | |
| 229 std::string tab_json = "null"; | |
| 230 if (source_contents) { | |
| 231 scoped_ptr<DictionaryValue> tab_value(ExtensionTabUtil::CreateTabValue( | |
| 232 source_contents)); | |
| 233 base::JSONWriter::Write(tab_value.get(), &tab_json); | |
| 234 } | |
| 235 | |
|
Matt Perry
2013/04/23 18:00:17
Why delete this?
not at google - send to devlin
2013/04/23 18:30:18
Maybe I'm missing something subtle (or obvious), b
Matt Perry
2013/04/23 18:39:37
Oh right, good point :)
| |
| 236 scoped_ptr<MessageChannel> channel(new MessageChannel()); | 239 scoped_ptr<MessageChannel> channel(new MessageChannel()); |
| 237 channel->opener.reset(new ExtensionMessagePort(source, MSG_ROUTING_CONTROL, | 240 channel->opener.reset(new ExtensionMessagePort(source, MSG_ROUTING_CONTROL, |
| 238 source_extension_id)); | 241 source_extension_id)); |
| 239 | 242 |
| 240 scoped_ptr<NativeMessageProcessHost> native_process = | 243 scoped_ptr<NativeMessageProcessHost> native_process = |
| 241 NativeMessageProcessHost::Create( | 244 NativeMessageProcessHost::Create( |
| 242 base::WeakPtr<NativeMessageProcessHost::Client>( | 245 base::WeakPtr<NativeMessageProcessHost::Client>( |
| 243 weak_factory_.GetWeakPtr()), | 246 weak_factory_.GetWeakPtr()), |
| 244 source_extension_id, native_app_name, receiver_port_id); | 247 source_extension_id, native_app_name, receiver_port_id); |
| 245 | 248 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 291 ExtensionMessagePort port(source, MSG_ROUTING_CONTROL, extension_id); | 294 ExtensionMessagePort port(source, MSG_ROUTING_CONTROL, extension_id); |
| 292 port.DispatchOnDisconnect(GET_OPPOSITE_PORT_ID(receiver_port_id), | 295 port.DispatchOnDisconnect(GET_OPPOSITE_PORT_ID(receiver_port_id), |
| 293 kReceivingEndDoesntExistError); | 296 kReceivingEndDoesntExistError); |
| 294 return; | 297 return; |
| 295 } | 298 } |
| 296 | 299 |
| 297 WebContents* source_contents = tab_util::GetWebContentsByID( | 300 WebContents* source_contents = tab_util::GetWebContentsByID( |
| 298 source_process_id, source_routing_id); | 301 source_process_id, source_routing_id); |
| 299 | 302 |
| 300 // Include info about the opener's tab (if it was a tab). | 303 // Include info about the opener's tab (if it was a tab). |
| 301 std::string tab_json = "null"; | 304 scoped_ptr<DictionaryValue> source_tab; |
| 302 if (source_contents) { | |
| 303 scoped_ptr<DictionaryValue> tab_value(ExtensionTabUtil::CreateTabValue( | |
| 304 source_contents)); | |
| 305 base::JSONWriter::Write(tab_value.get(), &tab_json); | |
| 306 } | |
| 307 | 305 |
| 308 scoped_ptr<OpenChannelParams> params(new OpenChannelParams(source, tab_json, | 306 if (source_contents && ExtensionTabUtil::GetTabId(source_contents) >= 0) |
| 309 receiver.release(), | 307 source_tab.reset(ExtensionTabUtil::CreateTabValue(source_contents)); |
| 310 receiver_port_id, | 308 |
| 311 extension_id, | 309 scoped_ptr<OpenChannelParams> params(new OpenChannelParams( |
| 312 extension_id, | 310 source, |
| 313 channel_name)); | 311 source_tab.Pass(), |
| 312 receiver.release(), | |
| 313 receiver_port_id, | |
| 314 extension_id, | |
| 315 extension_id, | |
| 316 GURL(), // source URL doesn't make sense for opening to tabs | |
|
Matt Perry
2013/04/23 18:00:17
Source tab doesn't make sense to me either. Do you
not at google - send to devlin
2013/04/23 18:30:18
Oh, right. Yeah we presumably included it before b
| |
| 317 channel_name)); | |
| 314 OpenChannelImpl(params.Pass()); | 318 OpenChannelImpl(params.Pass()); |
| 315 } | 319 } |
| 316 | 320 |
| 317 bool MessageService::OpenChannelImpl(scoped_ptr<OpenChannelParams> params) { | 321 bool MessageService::OpenChannelImpl(scoped_ptr<OpenChannelParams> params) { |
| 318 if (!params->source) | 322 if (!params->source) |
| 319 return false; // Closed while in flight. | 323 return false; // Closed while in flight. |
| 320 | 324 |
| 321 if (!params->receiver.get() || !params->receiver->GetRenderProcessHost()) { | 325 if (!params->receiver.get() || !params->receiver->GetRenderProcessHost()) { |
| 322 // Treat it as a disconnect. | 326 // Treat it as a disconnect. |
| 323 ExtensionMessagePort port( | 327 ExtensionMessagePort port( |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 339 | 343 |
| 340 CHECK(channel->receiver->GetRenderProcessHost()); | 344 CHECK(channel->receiver->GetRenderProcessHost()); |
| 341 | 345 |
| 342 AddChannel(channel, params->receiver_port_id); | 346 AddChannel(channel, params->receiver_port_id); |
| 343 | 347 |
| 344 CHECK(channel->receiver->GetRenderProcessHost()); | 348 CHECK(channel->receiver->GetRenderProcessHost()); |
| 345 | 349 |
| 346 // Send the connect event to the receiver. Give it the opener's port ID (the | 350 // Send the connect event to the receiver. Give it the opener's port ID (the |
| 347 // opener has the opposite port ID). | 351 // opener has the opposite port ID). |
| 348 channel->receiver->DispatchOnConnect(params->receiver_port_id, | 352 channel->receiver->DispatchOnConnect(params->receiver_port_id, |
| 349 params->channel_name, params->tab_json, | 353 params->channel_name, |
| 354 params->source_tab, | |
| 350 params->source_extension_id, | 355 params->source_extension_id, |
| 351 params->target_extension_id); | 356 params->target_extension_id, |
| 357 params->source_url); | |
| 352 | 358 |
| 353 // Keep both ends of the channel alive until the channel is closed. | 359 // Keep both ends of the channel alive until the channel is closed. |
| 354 channel->opener->IncrementLazyKeepaliveCount(); | 360 channel->opener->IncrementLazyKeepaliveCount(); |
| 355 channel->receiver->IncrementLazyKeepaliveCount(); | 361 channel->receiver->IncrementLazyKeepaliveCount(); |
| 356 return true; | 362 return true; |
| 357 } | 363 } |
| 358 | 364 |
| 359 void MessageService::AddChannel(MessageChannel* channel, int receiver_port_id) { | 365 void MessageService::AddChannel(MessageChannel* channel, int receiver_port_id) { |
| 360 int channel_id = GET_CHANNEL_ID(receiver_port_id); | 366 int channel_id = GET_CHANNEL_ID(receiver_port_id); |
| 361 CHECK(channels_.find(channel_id) == channels_.end()); | 367 CHECK(channels_.find(channel_id) == channels_.end()); |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 518 return; | 524 return; |
| 519 | 525 |
| 520 params->source = source; | 526 params->source = source; |
| 521 params->receiver.reset(new ExtensionMessagePort(host->render_process_host(), | 527 params->receiver.reset(new ExtensionMessagePort(host->render_process_host(), |
| 522 MSG_ROUTING_CONTROL, | 528 MSG_ROUTING_CONTROL, |
| 523 params->target_extension_id)); | 529 params->target_extension_id)); |
| 524 OpenChannelImpl(params.Pass()); | 530 OpenChannelImpl(params.Pass()); |
| 525 } | 531 } |
| 526 | 532 |
| 527 } // namespace extensions | 533 } // namespace extensions |
| OLD | NEW |