message_service.h revision 5821806d5e7f356e8fa4b058a389a808ea183019
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef CHROME_BROWSER_EXTENSIONS_API_MESSAGING_MESSAGE_SERVICE_H_ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHROME_BROWSER_EXTENSIONS_API_MESSAGING_MESSAGE_SERVICE_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/weak_ptr.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/messaging/native_message_process_host.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_observer.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_registrar.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Profile; 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RenderProcessHost; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class WebContents; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ExtensionHost; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class LazyBackgroundTaskQueue; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class manages message and event passing between renderer processes. 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It maintains a list of processes that are listening to events and a set of 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// open channels. 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Messaging works this way: 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - An extension-owned script context (like a background page or a content 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// script) adds an event listener to the "onConnect" event. 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Another context calls "extension.connect()" to open a channel to the 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// extension process, or an extension context calls "tabs.connect(tabId)" to 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// open a channel to the content scripts for the given tab. The EMS notifies 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the target process/tab, which then calls the onConnect event in every 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// context owned by the connecting extension in that process/tab. 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Once the channel is established, either side can call postMessage to send 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a message to the opposite side of the channel, which may have multiple 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// listeners. 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Terminology: 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// channel: connection between two ports 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// port: an IPC::Message::Process interface and an optional routing_id (in the 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// case that the port is a tab). The Process is usually either a 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// RenderProcessHost or a RenderViewHost. 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MessageService : public content::NotificationObserver, 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public NativeMessageProcessHost::Client { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A messaging channel. Note that the opening port can be the same as the 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // receiver, if an extension background page wants to talk to its tab (for 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // example). 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct MessageChannel; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // One side of the communication handled by extensions::MessageService. 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) class MessagePort { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~MessagePort() {} 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Notify the port that the channel has been opened. 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void DispatchOnConnect(int dest_port_id, 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& channel_name, 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& tab_json, 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& source_extension_id, 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& target_extension_id) {} 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Notify the port that the channel has been closed. 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void DispatchOnDisconnect(int source_port_id, 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool connection_error) {} 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Dispatch a message to this end of the communication. 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void DispatchOnMessage(const std::string& message, 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int target_port_id) = 0; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // MessagPorts that target extensions will need to adjust their keepalive 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // counts for their lazy background page. 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void IncrementLazyKeepaliveCount() {} 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void DecrementLazyKeepaliveCount() {} 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the RenderProcessHost (if any) associated with the port. 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual content::RenderProcessHost* GetRenderProcessHost(); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MessagePort() {} 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(MessagePort); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Allocates a pair of port ids. 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: this can be called from any thread. 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void AllocatePortIdPair(int* port1, int* port2); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit MessageService(LazyBackgroundTaskQueue* queue); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~MessageService(); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Given an extension's ID, opens a channel between the given renderer "port" 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and every listening context owned by that extension. |channel_name| is 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // an optional identifier for use by extension developers. 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void OpenChannelToExtension( 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int source_process_id, int source_routing_id, int receiver_port_id, 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& source_extension_id, 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& target_extension_id, 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& channel_name); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Same as above, but opens a channel to the tab with the given ID. Messages 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // are restricted to that tab, so if there are multiple tabs in that process, 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // only the targeted tab will receive messages. 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void OpenChannelToTab( 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int source_process_id, int source_routing_id, int receiver_port_id, 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int tab_id, const std::string& extension_id, 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& channel_name); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void OpenChannelToNativeApp( 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int source_process_id, 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int source_routing_id, 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int receiver_port_id, 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& source_extension_id, 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& native_app_name, 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& channel_name, 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& connect_message); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Should be called on the UI thread. 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void FinalizeOpenChannelToNativeApp( 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int receiver_port_id, 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& channel_name, 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<MessageChannel> channel, 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& tab_json, 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NativeMessageProcessHost::ScopedHost native_process); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Closes the message channel associated with the given port, and notifies 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the other side. 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void CloseChannel(int port_id, bool connection_error) OVERRIDE; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sends a message to the given port. 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void PostMessage(int port_id, const std::string& message); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NativeMessageProcessHost::Client 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void PostMessageFromNativeProcess( 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int port_id, const std::string& message) OVERRIDE; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class MockMessageService; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct OpenChannelParams; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A map of channel ID to its channel object. 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::map<int, MessageChannel*> MessageChannelMap; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A map of channel ID to information about the extension that is waiting 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for that channel to open. Used for lazy background pages. 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::string ExtensionID; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::pair<Profile*, ExtensionID> PendingChannel; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::map<int, PendingChannel> PendingChannelMap; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Common among OpenChannel* variants. 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool OpenChannelImpl(scoped_ptr<OpenChannelParams> params); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void CloseChannelImpl(MessageChannelMap::iterator channel_iter, 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int port_id, bool connection_error, 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool notify_other_port); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Have MessageService take ownership of |channel|, and remove any pending 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // channels with the same id. 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void AddChannel(MessageChannel* channel, int receiver_port_id); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // content::NotificationObserver interface. 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Observe(int type, 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationSource& source, 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationDetails& details) OVERRIDE; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A process that might be in our list of channels has closed. 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void OnProcessClosed(content::RenderProcessHost* process); 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Potentially registers a pending task with the LazyBackgroundTaskQueue 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to open a channel. Returns true if a task was queued. 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Takes ownership of |params| if true is returned. 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool MaybeAddPendingOpenChannelTask(Profile* profile, 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OpenChannelParams* params); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Callbacks for LazyBackgroundTaskQueue tasks. The queue passes in an 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ExtensionHost to its task callbacks, though some of our callbacks don't 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // use that argument. 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void PendingOpenChannel(scoped_ptr<OpenChannelParams> params, 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int source_process_id, 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions::ExtensionHost* host); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void PendingCloseChannel(int port_id, 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool connection_error, 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions::ExtensionHost* host) { 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (host) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseChannel(port_id, connection_error); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void PendingPostMessage(int port_id, 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& message, 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions::ExtensionHost* host) { 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (host) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PostMessage(port_id, message); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::NotificationRegistrar registrar_; 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MessageChannelMap channels_; 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PendingChannelMap pending_channels_; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Weak pointer. Guaranteed to outlive this class. 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LazyBackgroundTaskQueue* lazy_background_task_queue_; 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::WeakPtrFactory<MessageService> weak_factory_; 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(MessageService); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace extensions 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // CHROME_BROWSER_EXTENSIONS_API_MESSAGING_MESSAGE_SERVICE_H_ 217