Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(786)

Side by Side Diff: chrome/browser/extensions/api/messaging/message_service.cc

Issue 1272373003: Add extension event histogram values for messaging, webRequest, and webview. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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"
11 #include "base/lazy_instance.h" 11 #include "base/lazy_instance.h"
12 #include "base/metrics/histogram.h" 12 #include "base/metrics/histogram.h"
13 #include "base/prefs/pref_service.h" 13 #include "base/prefs/pref_service.h"
14 #include "base/stl_util.h" 14 #include "base/stl_util.h"
15 #include "chrome/browser/chrome_notification_types.h" 15 #include "chrome/browser/chrome_notification_types.h"
16 #include "chrome/browser/extensions/api/messaging/extension_message_port.h" 16 #include "chrome/browser/extensions/api/messaging/extension_message_port.h"
17 #include "chrome/browser/extensions/api/messaging/incognito_connectability.h" 17 #include "chrome/browser/extensions/api/messaging/incognito_connectability.h"
18 #include "chrome/browser/extensions/api/messaging/native_message_port.h" 18 #include "chrome/browser/extensions/api/messaging/native_message_port.h"
19 #include "chrome/browser/extensions/api/tabs/tabs_constants.h" 19 #include "chrome/browser/extensions/api/tabs/tabs_constants.h"
20 #include "chrome/browser/extensions/extension_service.h" 20 #include "chrome/browser/extensions/extension_service.h"
21 #include "chrome/browser/extensions/extension_tab_util.h" 21 #include "chrome/browser/extensions/extension_tab_util.h"
22 #include "chrome/browser/extensions/extension_util.h" 22 #include "chrome/browser/extensions/extension_util.h"
23 #include "chrome/browser/profiles/profile.h" 23 #include "chrome/browser/profiles/profile.h"
24 #include "chrome/browser/tab_contents/tab_util.h" 24 #include "chrome/browser/tab_contents/tab_util.h"
25 #include "components/guest_view/common/guest_view_constants.h" 25 #include "components/guest_view/common/guest_view_constants.h"
26 #include "content/public/browser/browser_thread.h"
26 #include "content/public/browser/notification_service.h" 27 #include "content/public/browser/notification_service.h"
27 #include "content/public/browser/render_frame_host.h" 28 #include "content/public/browser/render_frame_host.h"
28 #include "content/public/browser/render_process_host.h" 29 #include "content/public/browser/render_process_host.h"
29 #include "content/public/browser/render_view_host.h" 30 #include "content/public/browser/render_view_host.h"
30 #include "content/public/browser/render_widget_host.h" 31 #include "content/public/browser/render_widget_host.h"
31 #include "content/public/browser/render_widget_host_view.h" 32 #include "content/public/browser/render_widget_host_view.h"
32 #include "content/public/browser/site_instance.h" 33 #include "content/public/browser/site_instance.h"
33 #include "content/public/browser/web_contents.h" 34 #include "content/public/browser/web_contents.h"
34 #include "content/public/common/child_process_host.h" 35 #include "content/public/common/child_process_host.h"
35 #include "extensions/browser/event_router.h" 36 #include "extensions/browser/event_router.h"
36 #include "extensions/browser/extension_host.h" 37 #include "extensions/browser/extension_host.h"
37 #include "extensions/browser/extension_registry.h" 38 #include "extensions/browser/extension_registry.h"
38 #include "extensions/browser/extension_system.h" 39 #include "extensions/browser/extension_system.h"
39 #include "extensions/browser/extensions_browser_client.h" 40 #include "extensions/browser/extensions_browser_client.h"
40 #include "extensions/browser/guest_view/web_view/web_view_guest.h" 41 #include "extensions/browser/guest_view/web_view/web_view_guest.h"
41 #include "extensions/browser/lazy_background_task_queue.h" 42 #include "extensions/browser/lazy_background_task_queue.h"
42 #include "extensions/browser/pref_names.h" 43 #include "extensions/browser/pref_names.h"
43 #include "extensions/browser/process_manager.h" 44 #include "extensions/browser/process_manager.h"
44 #include "extensions/common/extension.h" 45 #include "extensions/common/extension.h"
45 #include "extensions/common/manifest_constants.h" 46 #include "extensions/common/manifest_constants.h"
46 #include "extensions/common/manifest_handlers/background_info.h" 47 #include "extensions/common/manifest_handlers/background_info.h"
47 #include "extensions/common/manifest_handlers/externally_connectable.h" 48 #include "extensions/common/manifest_handlers/externally_connectable.h"
48 #include "extensions/common/manifest_handlers/incognito_info.h" 49 #include "extensions/common/manifest_handlers/incognito_info.h"
49 #include "extensions/common/permissions/permissions_data.h" 50 #include "extensions/common/permissions/permissions_data.h"
50 #include "net/base/completion_callback.h" 51 #include "net/base/completion_callback.h"
51 #include "url/gurl.h" 52 #include "url/gurl.h"
52 53
53 using content::BrowserContext; 54 using content::BrowserContext;
55 using content::BrowserThread;
54 using content::SiteInstance; 56 using content::SiteInstance;
55 using content::WebContents; 57 using content::WebContents;
56 58
57 // Since we have 2 ports for every channel, we just index channels by half the 59 // Since we have 2 ports for every channel, we just index channels by half the
58 // port ID. 60 // port ID.
59 #define GET_CHANNEL_ID(port_id) ((port_id) / 2) 61 #define GET_CHANNEL_ID(port_id) ((port_id) / 2)
60 #define GET_CHANNEL_OPENER_ID(channel_id) ((channel_id) * 2) 62 #define GET_CHANNEL_OPENER_ID(channel_id) ((channel_id) * 2)
61 #define GET_CHANNEL_RECEIVERS_ID(channel_id) ((channel_id) * 2 + 1) 63 #define GET_CHANNEL_RECEIVERS_ID(channel_id) ((channel_id) * 2 + 1)
62 64
63 // Port1 is always even, port2 is always odd. 65 // Port1 is always even, port2 is always odd.
64 #define IS_OPENER_PORT_ID(port_id) (((port_id) & 1) == 0) 66 #define IS_OPENER_PORT_ID(port_id) (((port_id) & 1) == 0)
65 67
66 // Change even to odd and vice versa, to get the other side of a given channel. 68 // Change even to odd and vice versa, to get the other side of a given channel.
67 #define GET_OPPOSITE_PORT_ID(source_port_id) ((source_port_id) ^ 1) 69 #define GET_OPPOSITE_PORT_ID(source_port_id) ((source_port_id) ^ 1)
68 70
69 namespace extensions { 71 namespace extensions {
70 72
71 MessageService::PolicyPermission MessageService::IsNativeMessagingHostAllowed( 73 MessageService::PolicyPermission MessageService::IsNativeMessagingHostAllowed(
72 const PrefService* pref_service, 74 const PrefService* pref_service,
73 const std::string& native_host_name) { 75 const std::string& native_host_name) {
76 DCHECK_CURRENTLY_ON(BrowserThread::UI);
77
74 PolicyPermission allow_result = ALLOW_ALL; 78 PolicyPermission allow_result = ALLOW_ALL;
75 if (pref_service->IsManagedPreference( 79 if (pref_service->IsManagedPreference(
76 pref_names::kNativeMessagingUserLevelHosts)) { 80 pref_names::kNativeMessagingUserLevelHosts)) {
77 if (!pref_service->GetBoolean(pref_names::kNativeMessagingUserLevelHosts)) 81 if (!pref_service->GetBoolean(pref_names::kNativeMessagingUserLevelHosts))
78 allow_result = ALLOW_SYSTEM_ONLY; 82 allow_result = ALLOW_SYSTEM_ONLY;
79 } 83 }
80 84
81 // All native messaging hosts are allowed if there is no blacklist. 85 // All native messaging hosts are allowed if there is no blacklist.
82 if (!pref_service->IsManagedPreference(pref_names::kNativeMessagingBlacklist)) 86 if (!pref_service->IsManagedPreference(pref_names::kNativeMessagingBlacklist))
83 return allow_result; 87 return allow_result;
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 187
184 } // namespace 188 } // namespace
185 189
186 content::RenderProcessHost* 190 content::RenderProcessHost*
187 MessageService::MessagePort::GetRenderProcessHost() { 191 MessageService::MessagePort::GetRenderProcessHost() {
188 return NULL; 192 return NULL;
189 } 193 }
190 194
191 // static 195 // static
192 void MessageService::AllocatePortIdPair(int* port1, int* port2) { 196 void MessageService::AllocatePortIdPair(int* port1, int* port2) {
197 DCHECK_CURRENTLY_ON(BrowserThread::IO);
198
193 unsigned channel_id = 199 unsigned channel_id =
194 static_cast<unsigned>(g_next_channel_id.GetNext()) % (kint32max/2); 200 static_cast<unsigned>(g_next_channel_id.GetNext()) % (kint32max/2);
195 unsigned port1_id = channel_id * 2; 201 unsigned port1_id = channel_id * 2;
196 unsigned port2_id = channel_id * 2 + 1; 202 unsigned port2_id = channel_id * 2 + 1;
197 203
198 // Sanity checks to make sure our channel<->port converters are correct. 204 // Sanity checks to make sure our channel<->port converters are correct.
199 DCHECK(IS_OPENER_PORT_ID(port1_id)); 205 DCHECK(IS_OPENER_PORT_ID(port1_id));
200 DCHECK_EQ(GET_OPPOSITE_PORT_ID(port1_id), port2_id); 206 DCHECK_EQ(GET_OPPOSITE_PORT_ID(port1_id), port2_id);
201 DCHECK_EQ(GET_OPPOSITE_PORT_ID(port2_id), port1_id); 207 DCHECK_EQ(GET_OPPOSITE_PORT_ID(port2_id), port1_id);
202 DCHECK_EQ(GET_CHANNEL_ID(port1_id), GET_CHANNEL_ID(port2_id)); 208 DCHECK_EQ(GET_CHANNEL_ID(port1_id), GET_CHANNEL_ID(port2_id));
203 DCHECK_EQ(GET_CHANNEL_ID(port1_id), channel_id); 209 DCHECK_EQ(GET_CHANNEL_ID(port1_id), channel_id);
204 DCHECK_EQ(GET_CHANNEL_OPENER_ID(channel_id), port1_id); 210 DCHECK_EQ(GET_CHANNEL_OPENER_ID(channel_id), port1_id);
205 DCHECK_EQ(GET_CHANNEL_RECEIVERS_ID(channel_id), port2_id); 211 DCHECK_EQ(GET_CHANNEL_RECEIVERS_ID(channel_id), port2_id);
206 212
207 *port1 = port1_id; 213 *port1 = port1_id;
208 *port2 = port2_id; 214 *port2 = port2_id;
209 } 215 }
210 216
211 MessageService::MessageService(BrowserContext* context) 217 MessageService::MessageService(BrowserContext* context)
212 : lazy_background_task_queue_( 218 : lazy_background_task_queue_(
213 LazyBackgroundTaskQueue::Get(context)), 219 LazyBackgroundTaskQueue::Get(context)),
214 weak_factory_(this) { 220 weak_factory_(this) {
221 DCHECK_CURRENTLY_ON(BrowserThread::UI);
222
215 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, 223 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
216 content::NotificationService::AllBrowserContextsAndSources()); 224 content::NotificationService::AllBrowserContextsAndSources());
217 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, 225 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
218 content::NotificationService::AllBrowserContextsAndSources()); 226 content::NotificationService::AllBrowserContextsAndSources());
219 } 227 }
220 228
221 MessageService::~MessageService() { 229 MessageService::~MessageService() {
230 DCHECK_CURRENTLY_ON(BrowserThread::UI);
231
222 STLDeleteContainerPairSecondPointers(channels_.begin(), channels_.end()); 232 STLDeleteContainerPairSecondPointers(channels_.begin(), channels_.end());
223 channels_.clear(); 233 channels_.clear();
224 } 234 }
225 235
226 static base::LazyInstance<BrowserContextKeyedAPIFactory<MessageService> > 236 static base::LazyInstance<BrowserContextKeyedAPIFactory<MessageService> >
227 g_factory = LAZY_INSTANCE_INITIALIZER; 237 g_factory = LAZY_INSTANCE_INITIALIZER;
228 238
229 // static 239 // static
230 BrowserContextKeyedAPIFactory<MessageService>* 240 BrowserContextKeyedAPIFactory<MessageService>*
231 MessageService::GetFactoryInstance() { 241 MessageService::GetFactoryInstance() {
232 return g_factory.Pointer(); 242 return g_factory.Pointer();
233 } 243 }
234 244
235 // static 245 // static
236 MessageService* MessageService::Get(BrowserContext* context) { 246 MessageService* MessageService::Get(BrowserContext* context) {
237 return BrowserContextKeyedAPIFactory<MessageService>::Get(context); 247 return BrowserContextKeyedAPIFactory<MessageService>::Get(context);
238 } 248 }
239 249
240 void MessageService::OpenChannelToExtension( 250 void MessageService::OpenChannelToExtension(
241 int source_process_id, int source_routing_id, int receiver_port_id, 251 int source_process_id, int source_routing_id, int receiver_port_id,
242 const std::string& source_extension_id, 252 const std::string& source_extension_id,
243 const std::string& target_extension_id, 253 const std::string& target_extension_id,
244 const GURL& source_url, 254 const GURL& source_url,
245 const std::string& channel_name, 255 const std::string& channel_name,
246 bool include_tls_channel_id) { 256 bool include_tls_channel_id) {
257 DCHECK_CURRENTLY_ON(BrowserThread::UI);
258
247 content::RenderProcessHost* source = 259 content::RenderProcessHost* source =
248 content::RenderProcessHost::FromID(source_process_id); 260 content::RenderProcessHost::FromID(source_process_id);
249 if (!source) 261 if (!source)
250 return; 262 return;
251 BrowserContext* context = source->GetBrowserContext(); 263 BrowserContext* context = source->GetBrowserContext();
252 264
253 ExtensionRegistry* registry = ExtensionRegistry::Get(context); 265 ExtensionRegistry* registry = ExtensionRegistry::Get(context);
254 const Extension* target_extension = 266 const Extension* target_extension =
255 registry->enabled_extensions().GetByID(target_extension_id); 267 registry->enabled_extensions().GetByID(target_extension_id);
256 if (!target_extension) { 268 if (!target_extension) {
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
392 404
393 OnOpenChannelAllowed(params.Pass(), true); 405 OnOpenChannelAllowed(params.Pass(), true);
394 } 406 }
395 407
396 void MessageService::OpenChannelToNativeApp( 408 void MessageService::OpenChannelToNativeApp(
397 int source_process_id, 409 int source_process_id,
398 int source_routing_id, 410 int source_routing_id,
399 int receiver_port_id, 411 int receiver_port_id,
400 const std::string& source_extension_id, 412 const std::string& source_extension_id,
401 const std::string& native_app_name) { 413 const std::string& native_app_name) {
414 DCHECK_CURRENTLY_ON(BrowserThread::UI);
415
402 content::RenderProcessHost* source = 416 content::RenderProcessHost* source =
403 content::RenderProcessHost::FromID(source_process_id); 417 content::RenderProcessHost::FromID(source_process_id);
404 if (!source) 418 if (!source)
405 return; 419 return;
406 420
407 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) 421 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
408 Profile* profile = Profile::FromBrowserContext(source->GetBrowserContext()); 422 Profile* profile = Profile::FromBrowserContext(source->GetBrowserContext());
409 ExtensionService* extension_service = 423 ExtensionService* extension_service =
410 ExtensionSystem::Get(profile)->extension_service(); 424 ExtensionSystem::Get(profile)->extension_service();
411 bool has_permission = false; 425 bool has_permission = false;
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
470 source, receiver_port_id, kNativeMessagingNotSupportedError); 484 source, receiver_port_id, kNativeMessagingNotSupportedError);
471 #endif // !(defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)) 485 #endif // !(defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX))
472 } 486 }
473 487
474 void MessageService::OpenChannelToTab(int source_process_id, 488 void MessageService::OpenChannelToTab(int source_process_id,
475 int receiver_port_id, 489 int receiver_port_id,
476 int tab_id, 490 int tab_id,
477 int frame_id, 491 int frame_id,
478 const std::string& extension_id, 492 const std::string& extension_id,
479 const std::string& channel_name) { 493 const std::string& channel_name) {
494 DCHECK_CURRENTLY_ON(BrowserThread::UI);
495
480 content::RenderProcessHost* source = 496 content::RenderProcessHost* source =
481 content::RenderProcessHost::FromID(source_process_id); 497 content::RenderProcessHost::FromID(source_process_id);
482 if (!source) 498 if (!source)
483 return; 499 return;
484 Profile* profile = Profile::FromBrowserContext(source->GetBrowserContext()); 500 Profile* profile = Profile::FromBrowserContext(source->GetBrowserContext());
485 501
486 WebContents* contents = NULL; 502 WebContents* contents = NULL;
487 scoped_ptr<MessagePort> receiver; 503 scoped_ptr<MessagePort> receiver;
488 if (!ExtensionTabUtil::GetTabById(tab_id, profile, true, NULL, NULL, 504 if (!ExtensionTabUtil::GetTabById(tab_id, profile, true, NULL, NULL,
489 &contents, NULL) || 505 &contents, NULL) ||
(...skipping 19 matching lines...) Expand all
509 // Frame ID 0 is main frame. 525 // Frame ID 0 is main frame.
510 receiver_routing_id = contents->GetMainFrame()->GetRoutingID(); 526 receiver_routing_id = contents->GetMainFrame()->GetRoutingID();
511 } else { 527 } else {
512 DCHECK_EQ(-1, frame_id); 528 DCHECK_EQ(-1, frame_id);
513 // If the frame ID is not set (i.e. -1), then the channel has to be opened 529 // If the frame ID is not set (i.e. -1), then the channel has to be opened
514 // in every frame. 530 // in every frame.
515 // TODO(robwu): Update logic so that frames that are not hosted in the main 531 // TODO(robwu): Update logic so that frames that are not hosted in the main
516 // frame's process can also receive the port. 532 // frame's process can also receive the port.
517 receiver_routing_id = MSG_ROUTING_CONTROL; 533 receiver_routing_id = MSG_ROUTING_CONTROL;
518 } 534 }
519 receiver.reset(new ExtensionMessagePort( 535 receiver.reset(new ExtensionMessagePort(contents->GetRenderProcessHost(),
520 contents->GetRenderProcessHost(), receiver_routing_id, extension_id)); 536 receiver_routing_id, extension_id));
521 537
522 scoped_ptr<OpenChannelParams> params(new OpenChannelParams( 538 scoped_ptr<OpenChannelParams> params(new OpenChannelParams(
523 source_process_id, 539 source_process_id,
524 scoped_ptr<base::DictionaryValue>(), // Source tab doesn't make sense 540 scoped_ptr<base::DictionaryValue>(), // Source tab doesn't make sense
525 // for opening to tabs. 541 // for opening to tabs.
526 -1, // If there is no tab, then there is no frame either. 542 -1, // If there is no tab, then there is no frame either.
527 frame_id, 543 frame_id,
528 receiver.release(), receiver_port_id, extension_id, extension_id, 544 receiver.release(), receiver_port_id, extension_id, extension_id,
529 GURL(), // Source URL doesn't make sense for opening to tabs. 545 GURL(), // Source URL doesn't make sense for opening to tabs.
530 channel_name, 546 channel_name,
531 false, // Connections to tabs don't get TLS channel IDs. 547 false, // Connections to tabs don't get TLS channel IDs.
532 false)); // Connections to tabs aren't webview guests. 548 false)); // Connections to tabs aren't webview guests.
533 OpenChannelImpl(params.Pass()); 549 OpenChannelImpl(contents->GetBrowserContext(), params.Pass(), false);
534 } 550 }
535 551
536 void MessageService::OpenChannelImpl(scoped_ptr<OpenChannelParams> params) { 552 void MessageService::OpenChannelImpl(BrowserContext* browser_context,
553 scoped_ptr<OpenChannelParams> params,
554 bool did_enqueue) {
555 DCHECK_CURRENTLY_ON(BrowserThread::UI);
556
537 content::RenderProcessHost* source = 557 content::RenderProcessHost* source =
538 content::RenderProcessHost::FromID(params->source_process_id); 558 content::RenderProcessHost::FromID(params->source_process_id);
539 if (!source) 559 if (!source)
540 return; // Closed while in flight. 560 return; // Closed while in flight.
541 561
542 if (!params->receiver || !params->receiver->GetRenderProcessHost()) { 562 if (!params->receiver || !params->receiver->GetRenderProcessHost()) {
543 DispatchOnDisconnect(source, params->receiver_port_id, 563 DispatchOnDisconnect(source, params->receiver_port_id,
544 kReceivingEndDoesntExistError); 564 kReceivingEndDoesntExistError);
545 return; 565 return;
546 } 566 }
547 567
548 // Add extra paranoid CHECKs, since we have crash reports of this being NULL.
549 // http://code.google.com/p/chromium/issues/detail?id=19067
550 CHECK(params->receiver->GetRenderProcessHost());
551
552 MessageChannel* channel(new MessageChannel); 568 MessageChannel* channel(new MessageChannel);
553 channel->opener.reset(new ExtensionMessagePort(source, MSG_ROUTING_CONTROL, 569 channel->opener.reset(new ExtensionMessagePort(source, MSG_ROUTING_CONTROL,
554 params->source_extension_id)); 570 params->source_extension_id));
555 channel->receiver.reset(params->receiver.release()); 571 channel->receiver.reset(params->receiver.release());
556
557 CHECK(channel->receiver->GetRenderProcessHost());
558
559 AddChannel(channel, params->receiver_port_id); 572 AddChannel(channel, params->receiver_port_id);
560 573
561 CHECK(channel->receiver->GetRenderProcessHost());
562
563 int guest_process_id = content::ChildProcessHost::kInvalidUniqueID; 574 int guest_process_id = content::ChildProcessHost::kInvalidUniqueID;
564 int guest_render_frame_routing_id = MSG_ROUTING_NONE; 575 int guest_render_frame_routing_id = MSG_ROUTING_NONE;
565 if (params->include_guest_process_info) { 576 if (params->include_guest_process_info) {
566 guest_process_id = params->source_process_id; 577 guest_process_id = params->source_process_id;
567 guest_render_frame_routing_id = params->source_frame_id; 578 guest_render_frame_routing_id = params->source_frame_id;
568 auto* guest_rfh = content::RenderFrameHost::FromID( 579 auto* guest_rfh = content::RenderFrameHost::FromID(
569 guest_process_id, guest_render_frame_routing_id); 580 guest_process_id, guest_render_frame_routing_id);
570 // Reset the |source_frame_id| parameter. 581 // Reset the |source_frame_id| parameter.
571 params->source_frame_id = -1; 582 params->source_frame_id = -1;
572 583
573 DCHECK(guest_rfh == nullptr || 584 DCHECK(guest_rfh == nullptr ||
574 WebViewGuest::FromWebContents( 585 WebViewGuest::FromWebContents(
575 WebContents::FromRenderFrameHost(guest_rfh)) != nullptr); 586 WebContents::FromRenderFrameHost(guest_rfh)) != nullptr);
576 } 587 }
577 588
578 // Send the connect event to the receiver. Give it the opener's port ID (the 589 // Send the connect event to the receiver. Give it the opener's port ID (the
579 // opener has the opposite port ID). 590 // opener has the opposite port ID).
580 channel->receiver->DispatchOnConnect(params->receiver_port_id, 591 channel->receiver->DispatchOnConnect(
581 params->channel_name, 592 params->receiver_port_id, params->channel_name, params->source_tab.Pass(),
582 params->source_tab.Pass(), 593 params->source_frame_id, params->target_frame_id, guest_process_id,
583 params->source_frame_id, 594 guest_render_frame_routing_id, params->source_extension_id,
584 params->target_frame_id, 595 params->target_extension_id, params->source_url, params->tls_channel_id);
585 guest_process_id, 596
586 guest_render_frame_routing_id, 597 // Report the event to the event router.
587 params->source_extension_id, 598 //
588 params->target_extension_id, 599 // First, determine what event this will be (runtime.onConnect vs
589 params->source_url, 600 // runtime.onMessage etc), and what the event target is (view vs background
590 params->tls_channel_id); 601 // page etc).
602 //
603 // Yes - even though this is opening a channel, they may actually be
604 // runtime.onRequest/onMessage events because those single-use events are
605 // built using the connect framework (see messaging.js).
606 //
607 // Likewise, if you're wondering about native messaging events, these are
608 // only initiated *by* the extension, so aren't really events, just the
609 // endpoint of a communication channel.
610 events::HistogramValue histogram_value = events::UNKNOWN;
611 bool is_external = params->source_extension_id != params->target_extension_id;
612 if (params->channel_name == "chrome.runtime.onRequest") {
613 histogram_value = is_external ? events::RUNTIME_ON_REQUEST_EXTERNAL
614 : events::RUNTIME_ON_REQUEST;
615 } else if (params->channel_name == "chrome.runtime.onMessage") {
616 histogram_value = is_external ? events::RUNTIME_ON_MESSAGE_EXTERNAL
617 : events::RUNTIME_ON_MESSAGE;
618 } else {
619 histogram_value = is_external ? events::RUNTIME_ON_CONNECT_EXTERNAL
620 : events::RUNTIME_ON_CONNECT;
621 }
622 EventRouter::Get(browser_context)
623 ->ReportEvent(histogram_value, GURL(), did_enqueue);
591 624
592 // Keep both ends of the channel alive until the channel is closed. 625 // Keep both ends of the channel alive until the channel is closed.
593 channel->opener->IncrementLazyKeepaliveCount(); 626 channel->opener->IncrementLazyKeepaliveCount();
594 channel->receiver->IncrementLazyKeepaliveCount(); 627 channel->receiver->IncrementLazyKeepaliveCount();
595 } 628 }
596 629
597 void MessageService::AddChannel(MessageChannel* channel, int receiver_port_id) { 630 void MessageService::AddChannel(MessageChannel* channel, int receiver_port_id) {
631 DCHECK_CURRENTLY_ON(BrowserThread::UI);
632
598 int channel_id = GET_CHANNEL_ID(receiver_port_id); 633 int channel_id = GET_CHANNEL_ID(receiver_port_id);
599 CHECK(channels_.find(channel_id) == channels_.end()); 634 CHECK(channels_.find(channel_id) == channels_.end());
600 channels_[channel_id] = channel; 635 channels_[channel_id] = channel;
601 pending_lazy_background_page_channels_.erase(channel_id); 636 pending_lazy_background_page_channels_.erase(channel_id);
602 } 637 }
603 638
604 void MessageService::CloseChannel(int port_id, 639 void MessageService::CloseChannel(int port_id,
605 const std::string& error_message) { 640 const std::string& error_message) {
641 DCHECK_CURRENTLY_ON(BrowserThread::UI);
642
606 // Note: The channel might be gone already, if the other side closed first. 643 // Note: The channel might be gone already, if the other side closed first.
607 int channel_id = GET_CHANNEL_ID(port_id); 644 int channel_id = GET_CHANNEL_ID(port_id);
608 MessageChannelMap::iterator it = channels_.find(channel_id); 645 MessageChannelMap::iterator it = channels_.find(channel_id);
609 if (it == channels_.end()) { 646 if (it == channels_.end()) {
610 PendingLazyBackgroundPageChannelMap::iterator pending = 647 PendingLazyBackgroundPageChannelMap::iterator pending =
611 pending_lazy_background_page_channels_.find(channel_id); 648 pending_lazy_background_page_channels_.find(channel_id);
612 if (pending != pending_lazy_background_page_channels_.end()) { 649 if (pending != pending_lazy_background_page_channels_.end()) {
613 lazy_background_task_queue_->AddPendingTask( 650 lazy_background_task_queue_->AddPendingTask(
614 pending->second.first, pending->second.second, 651 pending->second.first, pending->second.second,
615 base::Bind(&MessageService::PendingLazyBackgroundPageCloseChannel, 652 base::Bind(&MessageService::PendingLazyBackgroundPageCloseChannel,
616 weak_factory_.GetWeakPtr(), port_id, error_message)); 653 weak_factory_.GetWeakPtr(), port_id, error_message));
617 } 654 }
618 return; 655 return;
619 } 656 }
620 CloseChannelImpl(it, port_id, error_message, true); 657 CloseChannelImpl(it, port_id, error_message, true);
621 } 658 }
622 659
623 void MessageService::CloseChannelImpl( 660 void MessageService::CloseChannelImpl(
624 MessageChannelMap::iterator channel_iter, 661 MessageChannelMap::iterator channel_iter,
625 int closing_port_id, 662 int closing_port_id,
626 const std::string& error_message, 663 const std::string& error_message,
627 bool notify_other_port) { 664 bool notify_other_port) {
665 DCHECK_CURRENTLY_ON(BrowserThread::UI);
666
628 MessageChannel* channel = channel_iter->second; 667 MessageChannel* channel = channel_iter->second;
629 668
630 // Notify the other side. 669 // Notify the other side.
631 if (notify_other_port) { 670 if (notify_other_port) {
632 MessagePort* port = IS_OPENER_PORT_ID(closing_port_id) ? 671 MessagePort* port = IS_OPENER_PORT_ID(closing_port_id) ?
633 channel->receiver.get() : channel->opener.get(); 672 channel->receiver.get() : channel->opener.get();
634 port->DispatchOnDisconnect(GET_OPPOSITE_PORT_ID(closing_port_id), 673 port->DispatchOnDisconnect(GET_OPPOSITE_PORT_ID(closing_port_id),
635 error_message); 674 error_message);
636 } 675 }
637 676
638 // Balance the IncrementLazyKeepaliveCount() in OpenChannelImpl. 677 // Balance the IncrementLazyKeepaliveCount() in OpenChannelImpl.
639 channel->opener->DecrementLazyKeepaliveCount(); 678 channel->opener->DecrementLazyKeepaliveCount();
640 channel->receiver->DecrementLazyKeepaliveCount(); 679 channel->receiver->DecrementLazyKeepaliveCount();
641 680
642 delete channel_iter->second; 681 delete channel_iter->second;
643 channels_.erase(channel_iter); 682 channels_.erase(channel_iter);
644 } 683 }
645 684
646 void MessageService::PostMessage(int source_port_id, const Message& message) { 685 void MessageService::PostMessage(int source_port_id, const Message& message) {
686 DCHECK_CURRENTLY_ON(BrowserThread::UI);
687
647 int channel_id = GET_CHANNEL_ID(source_port_id); 688 int channel_id = GET_CHANNEL_ID(source_port_id);
648 MessageChannelMap::iterator iter = channels_.find(channel_id); 689 MessageChannelMap::iterator iter = channels_.find(channel_id);
649 if (iter == channels_.end()) { 690 if (iter == channels_.end()) {
650 // If this channel is pending, queue up the PostMessage to run once 691 // If this channel is pending, queue up the PostMessage to run once
651 // the channel opens. 692 // the channel opens.
652 EnqueuePendingMessage(source_port_id, channel_id, message); 693 EnqueuePendingMessage(source_port_id, channel_id, message);
653 return; 694 return;
654 } 695 }
655 696
656 DispatchMessage(source_port_id, iter->second, message); 697 DispatchMessage(source_port_id, iter->second, message);
657 } 698 }
658 699
659 void MessageService::Observe(int type, 700 void MessageService::Observe(int type,
660 const content::NotificationSource& source, 701 const content::NotificationSource& source,
661 const content::NotificationDetails& details) { 702 const content::NotificationDetails& details) {
703 DCHECK_CURRENTLY_ON(BrowserThread::UI);
704
662 switch (type) { 705 switch (type) {
663 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: 706 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED:
664 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: { 707 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: {
665 content::RenderProcessHost* renderer = 708 content::RenderProcessHost* renderer =
666 content::Source<content::RenderProcessHost>(source).ptr(); 709 content::Source<content::RenderProcessHost>(source).ptr();
667 OnProcessClosed(renderer); 710 OnProcessClosed(renderer);
668 break; 711 break;
669 } 712 }
670 default: 713 default:
671 NOTREACHED(); 714 NOTREACHED();
672 return; 715 return;
673 } 716 }
674 } 717 }
675 718
676 void MessageService::OnProcessClosed(content::RenderProcessHost* process) { 719 void MessageService::OnProcessClosed(content::RenderProcessHost* process) {
720 DCHECK_CURRENTLY_ON(BrowserThread::UI);
721
677 // Close any channels that share this renderer. We notify the opposite 722 // Close any channels that share this renderer. We notify the opposite
678 // port that his pair has closed. 723 // port that its pair has closed.
679 for (MessageChannelMap::iterator it = channels_.begin(); 724 for (MessageChannelMap::iterator it = channels_.begin();
680 it != channels_.end(); ) { 725 it != channels_.end(); ) {
681 MessageChannelMap::iterator current = it++; 726 MessageChannelMap::iterator current = it++;
682 727
683 content::RenderProcessHost* opener_process = 728 content::RenderProcessHost* opener_process =
684 current->second->opener->GetRenderProcessHost(); 729 current->second->opener->GetRenderProcessHost();
685 content::RenderProcessHost* receiver_process = 730 content::RenderProcessHost* receiver_process =
686 current->second->receiver->GetRenderProcessHost(); 731 current->second->receiver->GetRenderProcessHost();
687 732
688 // Only notify the other side if it has a different porocess host. 733 // Only notify the other side if it has a different porocess host.
689 bool notify_other_port = opener_process && receiver_process && 734 bool notify_other_port = opener_process && receiver_process &&
690 opener_process != receiver_process; 735 opener_process != receiver_process;
691 736
692 if (opener_process == process) { 737 if (opener_process == process) {
693 CloseChannelImpl(current, GET_CHANNEL_OPENER_ID(current->first), 738 CloseChannelImpl(current, GET_CHANNEL_OPENER_ID(current->first),
694 std::string(), notify_other_port); 739 std::string(), notify_other_port);
695 } else if (receiver_process == process) { 740 } else if (receiver_process == process) {
696 CloseChannelImpl(current, GET_CHANNEL_RECEIVERS_ID(current->first), 741 CloseChannelImpl(current, GET_CHANNEL_RECEIVERS_ID(current->first),
697 std::string(), notify_other_port); 742 std::string(), notify_other_port);
698 } 743 }
699 } 744 }
700 } 745 }
701 746
702 void MessageService::EnqueuePendingMessage(int source_port_id, 747 void MessageService::EnqueuePendingMessage(int source_port_id,
703 int channel_id, 748 int channel_id,
704 const Message& message) { 749 const Message& message) {
750 DCHECK_CURRENTLY_ON(BrowserThread::UI);
751
705 PendingChannelMap::iterator pending_for_incognito = 752 PendingChannelMap::iterator pending_for_incognito =
706 pending_incognito_channels_.find(channel_id); 753 pending_incognito_channels_.find(channel_id);
707 if (pending_for_incognito != pending_incognito_channels_.end()) { 754 if (pending_for_incognito != pending_incognito_channels_.end()) {
708 pending_for_incognito->second.push_back( 755 pending_for_incognito->second.push_back(
709 PendingMessage(source_port_id, message)); 756 PendingMessage(source_port_id, message));
710 // A channel should only be holding pending messages because it is in one 757 // A channel should only be holding pending messages because it is in one
711 // of these states. 758 // of these states.
712 DCHECK(!ContainsKey(pending_tls_channel_id_channels_, channel_id)); 759 DCHECK(!ContainsKey(pending_tls_channel_id_channels_, channel_id));
713 DCHECK(!ContainsKey(pending_lazy_background_page_channels_, channel_id)); 760 DCHECK(!ContainsKey(pending_lazy_background_page_channels_, channel_id));
714 return; 761 return;
(...skipping 10 matching lines...) Expand all
725 } 772 }
726 EnqueuePendingMessageForLazyBackgroundLoad(source_port_id, 773 EnqueuePendingMessageForLazyBackgroundLoad(source_port_id,
727 channel_id, 774 channel_id,
728 message); 775 message);
729 } 776 }
730 777
731 void MessageService::EnqueuePendingMessageForLazyBackgroundLoad( 778 void MessageService::EnqueuePendingMessageForLazyBackgroundLoad(
732 int source_port_id, 779 int source_port_id,
733 int channel_id, 780 int channel_id,
734 const Message& message) { 781 const Message& message) {
782 DCHECK_CURRENTLY_ON(BrowserThread::UI);
783
735 PendingLazyBackgroundPageChannelMap::iterator pending = 784 PendingLazyBackgroundPageChannelMap::iterator pending =
736 pending_lazy_background_page_channels_.find(channel_id); 785 pending_lazy_background_page_channels_.find(channel_id);
737 if (pending != pending_lazy_background_page_channels_.end()) { 786 if (pending != pending_lazy_background_page_channels_.end()) {
738 lazy_background_task_queue_->AddPendingTask( 787 lazy_background_task_queue_->AddPendingTask(
739 pending->second.first, pending->second.second, 788 pending->second.first, pending->second.second,
740 base::Bind(&MessageService::PendingLazyBackgroundPagePostMessage, 789 base::Bind(&MessageService::PendingLazyBackgroundPagePostMessage,
741 weak_factory_.GetWeakPtr(), source_port_id, message)); 790 weak_factory_.GetWeakPtr(), source_port_id, message));
742 } 791 }
743 } 792 }
744 793
745 void MessageService::DispatchMessage(int source_port_id, 794 void MessageService::DispatchMessage(int source_port_id,
746 MessageChannel* channel, 795 MessageChannel* channel,
747 const Message& message) { 796 const Message& message) {
797 DCHECK_CURRENTLY_ON(BrowserThread::UI);
798
748 // Figure out which port the ID corresponds to. 799 // Figure out which port the ID corresponds to.
749 int dest_port_id = GET_OPPOSITE_PORT_ID(source_port_id); 800 int dest_port_id = GET_OPPOSITE_PORT_ID(source_port_id);
750 MessagePort* port = IS_OPENER_PORT_ID(dest_port_id) ? 801 MessagePort* port = IS_OPENER_PORT_ID(dest_port_id) ?
751 channel->opener.get() : channel->receiver.get(); 802 channel->opener.get() : channel->receiver.get();
752 803
753 port->DispatchOnMessage(message, dest_port_id); 804 port->DispatchOnMessage(message, dest_port_id);
754 } 805 }
755 806
756 bool MessageService::MaybeAddPendingLazyBackgroundPageOpenChannelTask( 807 bool MessageService::MaybeAddPendingLazyBackgroundPageOpenChannelTask(
757 BrowserContext* context, 808 BrowserContext* context,
758 const Extension* extension, 809 const Extension* extension,
759 scoped_ptr<OpenChannelParams>* params, 810 scoped_ptr<OpenChannelParams>* params,
760 const PendingMessagesQueue& pending_messages) { 811 const PendingMessagesQueue& pending_messages) {
812 DCHECK_CURRENTLY_ON(BrowserThread::UI);
813
761 if (!BackgroundInfo::HasLazyBackgroundPage(extension)) 814 if (!BackgroundInfo::HasLazyBackgroundPage(extension))
762 return false; 815 return false;
763 816
764 // If the extension uses spanning incognito mode, make sure we're always 817 // If the extension uses spanning incognito mode, make sure we're always
765 // using the original profile since that is what the extension process 818 // using the original profile since that is what the extension process
766 // will use. 819 // will use.
767 if (!IncognitoInfo::IsSplitMode(extension)) 820 if (!IncognitoInfo::IsSplitMode(extension))
768 context = ExtensionsBrowserClient::Get()->GetOriginalContext(context); 821 context = ExtensionsBrowserClient::Get()->GetOriginalContext(context);
769 822
770 if (!lazy_background_task_queue_->ShouldEnqueueTask(context, extension)) 823 if (!lazy_background_task_queue_->ShouldEnqueueTask(context, extension))
(...skipping 10 matching lines...) Expand all
781 834
782 for (const PendingMessage& message : pending_messages) { 835 for (const PendingMessage& message : pending_messages) {
783 EnqueuePendingMessageForLazyBackgroundLoad(message.first, channel_id, 836 EnqueuePendingMessageForLazyBackgroundLoad(message.first, channel_id,
784 message.second); 837 message.second);
785 } 838 }
786 return true; 839 return true;
787 } 840 }
788 841
789 void MessageService::OnOpenChannelAllowed(scoped_ptr<OpenChannelParams> params, 842 void MessageService::OnOpenChannelAllowed(scoped_ptr<OpenChannelParams> params,
790 bool allowed) { 843 bool allowed) {
844 DCHECK_CURRENTLY_ON(BrowserThread::UI);
845
791 int channel_id = GET_CHANNEL_ID(params->receiver_port_id); 846 int channel_id = GET_CHANNEL_ID(params->receiver_port_id);
792 847
793 PendingChannelMap::iterator pending_for_incognito = 848 PendingChannelMap::iterator pending_for_incognito =
794 pending_incognito_channels_.find(channel_id); 849 pending_incognito_channels_.find(channel_id);
795 if (pending_for_incognito == pending_incognito_channels_.end()) { 850 if (pending_for_incognito == pending_incognito_channels_.end()) {
796 NOTREACHED(); 851 NOTREACHED();
797 return; 852 return;
798 } 853 }
799 PendingMessagesQueue pending_messages; 854 PendingMessagesQueue pending_messages;
800 pending_messages.swap(pending_for_incognito->second); 855 pending_messages.swap(pending_for_incognito->second);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
845 DispatchOnDisconnect(source, params->receiver_port_id, 900 DispatchOnDisconnect(source, params->receiver_port_id,
846 kReceivingEndDoesntExistError); 901 kReceivingEndDoesntExistError);
847 return; 902 return;
848 } 903 }
849 904
850 // The target might be a lazy background page. In that case, we have to check 905 // The target might be a lazy background page. In that case, we have to check
851 // if it is loaded and ready, and if not, queue up the task and load the 906 // if it is loaded and ready, and if not, queue up the task and load the
852 // page. 907 // page.
853 if (!MaybeAddPendingLazyBackgroundPageOpenChannelTask( 908 if (!MaybeAddPendingLazyBackgroundPageOpenChannelTask(
854 context, target_extension, &params, pending_messages)) { 909 context, target_extension, &params, pending_messages)) {
855 OpenChannelImpl(params.Pass()); 910 OpenChannelImpl(context, params.Pass(), false);
856 DispatchPendingMessages(pending_messages, channel_id); 911 DispatchPendingMessages(pending_messages, channel_id);
857 } 912 }
858 } 913 }
859 914
860 void MessageService::GotChannelID(scoped_ptr<OpenChannelParams> params, 915 void MessageService::GotChannelID(scoped_ptr<OpenChannelParams> params,
861 const std::string& tls_channel_id) { 916 const std::string& tls_channel_id) {
917 DCHECK_CURRENTLY_ON(BrowserThread::UI);
918
862 params->tls_channel_id.assign(tls_channel_id); 919 params->tls_channel_id.assign(tls_channel_id);
863 int channel_id = GET_CHANNEL_ID(params->receiver_port_id); 920 int channel_id = GET_CHANNEL_ID(params->receiver_port_id);
864 921
865 PendingChannelMap::iterator pending_for_tls_channel_id = 922 PendingChannelMap::iterator pending_for_tls_channel_id =
866 pending_tls_channel_id_channels_.find(channel_id); 923 pending_tls_channel_id_channels_.find(channel_id);
867 if (pending_for_tls_channel_id == pending_tls_channel_id_channels_.end()) { 924 if (pending_for_tls_channel_id == pending_tls_channel_id_channels_.end()) {
868 NOTREACHED(); 925 NOTREACHED();
869 return; 926 return;
870 } 927 }
871 PendingMessagesQueue pending_messages; 928 PendingMessagesQueue pending_messages;
(...skipping 12 matching lines...) Expand all
884 const Extension* target_extension = 941 const Extension* target_extension =
885 registry->enabled_extensions().GetByID(params->target_extension_id); 942 registry->enabled_extensions().GetByID(params->target_extension_id);
886 if (!target_extension) { 943 if (!target_extension) {
887 DispatchOnDisconnect(source, params->receiver_port_id, 944 DispatchOnDisconnect(source, params->receiver_port_id,
888 kReceivingEndDoesntExistError); 945 kReceivingEndDoesntExistError);
889 return; 946 return;
890 } 947 }
891 948
892 if (!MaybeAddPendingLazyBackgroundPageOpenChannelTask( 949 if (!MaybeAddPendingLazyBackgroundPageOpenChannelTask(
893 context, target_extension, &params, pending_messages)) { 950 context, target_extension, &params, pending_messages)) {
894 OpenChannelImpl(params.Pass()); 951 OpenChannelImpl(context, params.Pass(), false);
895 DispatchPendingMessages(pending_messages, channel_id); 952 DispatchPendingMessages(pending_messages, channel_id);
896 } 953 }
897 } 954 }
898 955
899 void MessageService::PendingLazyBackgroundPageOpenChannel( 956 void MessageService::PendingLazyBackgroundPageOpenChannel(
900 scoped_ptr<OpenChannelParams> params, 957 scoped_ptr<OpenChannelParams> params,
901 int source_process_id, 958 int source_process_id,
902 ExtensionHost* host) { 959 ExtensionHost* host) {
960 DCHECK_CURRENTLY_ON(BrowserThread::UI);
961
903 if (!host) 962 if (!host)
904 return; // TODO(mpcomplete): notify source of disconnect? 963 return; // TODO(mpcomplete): notify source of disconnect?
905 964
906 params->receiver.reset(new ExtensionMessagePort(host->render_process_host(), 965 params->receiver.reset(new ExtensionMessagePort(host->render_process_host(),
907 MSG_ROUTING_CONTROL, 966 MSG_ROUTING_CONTROL,
908 params->target_extension_id)); 967 params->target_extension_id));
909 OpenChannelImpl(params.Pass()); 968 OpenChannelImpl(host->browser_context(), params.Pass(), true);
910 } 969 }
911 970
912 void MessageService::DispatchOnDisconnect(content::RenderProcessHost* source, 971 void MessageService::DispatchOnDisconnect(content::RenderProcessHost* source,
913 int port_id, 972 int port_id,
914 const std::string& error_message) { 973 const std::string& error_message) {
974 DCHECK_CURRENTLY_ON(BrowserThread::UI);
975
915 ExtensionMessagePort port(source, MSG_ROUTING_CONTROL, ""); 976 ExtensionMessagePort port(source, MSG_ROUTING_CONTROL, "");
916 port.DispatchOnDisconnect(GET_OPPOSITE_PORT_ID(port_id), error_message); 977 port.DispatchOnDisconnect(GET_OPPOSITE_PORT_ID(port_id), error_message);
917 } 978 }
918 979
919 void MessageService::DispatchPendingMessages(const PendingMessagesQueue& queue, 980 void MessageService::DispatchPendingMessages(const PendingMessagesQueue& queue,
920 int channel_id) { 981 int channel_id) {
982 DCHECK_CURRENTLY_ON(BrowserThread::UI);
983
921 MessageChannelMap::iterator channel_iter = channels_.find(channel_id); 984 MessageChannelMap::iterator channel_iter = channels_.find(channel_id);
922 if (channel_iter != channels_.end()) { 985 if (channel_iter != channels_.end()) {
923 for (const PendingMessage& message : queue) { 986 for (const PendingMessage& message : queue) {
924 DispatchMessage(message.first, channel_iter->second, message.second); 987 DispatchMessage(message.first, channel_iter->second, message.second);
925 } 988 }
926 } 989 }
927 } 990 }
928 991
929 } // namespace extensions 992 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698