1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "extensions/browser/extension_message_filter.h"
7 #include "base/memory/singleton.h"
8 #include "components/crx_file/id_util.h"
9 #include "components/keyed_service/content/browser_context_keyed_service_shutdown_notifier_factory.h"
10 #include "content/public/browser/browser_thread.h"
11 #include "content/public/browser/render_process_host.h"
12 #include "extensions/browser/blob_holder.h"
13 #include "extensions/browser/event_router.h"
14 #include "extensions/browser/event_router_factory.h"
15 #include "extensions/browser/process_manager.h"
16 #include "extensions/browser/process_manager_factory.h"
17 #include "extensions/common/extension.h"
18 #include "extensions/common/extension_messages.h"
19 #include "ipc/ipc_message_macros.h"
21 using content::BrowserThread
;
22 using content::RenderProcessHost
;
24 namespace extensions
{
28 class ShutdownNotifierFactory
29 : public BrowserContextKeyedServiceShutdownNotifierFactory
{
31 static ShutdownNotifierFactory
* GetInstance() {
32 return Singleton
<ShutdownNotifierFactory
>::get();
36 friend struct DefaultSingletonTraits
<ShutdownNotifierFactory
>;
38 ShutdownNotifierFactory()
39 : BrowserContextKeyedServiceShutdownNotifierFactory(
40 "ExtensionMessageFilter") {
41 DependsOn(EventRouterFactory::GetInstance());
42 DependsOn(ProcessManagerFactory::GetInstance());
44 ~ShutdownNotifierFactory() override
{}
46 DISALLOW_COPY_AND_ASSIGN(ShutdownNotifierFactory
);
51 ExtensionMessageFilter::ExtensionMessageFilter(int render_process_id
,
52 content::BrowserContext
* context
)
53 : BrowserMessageFilter(ExtensionMsgStart
),
54 render_process_id_(render_process_id
),
55 event_router_(EventRouter::Get(context
)),
56 process_manager_(ProcessManager::Get(context
)) {
57 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
59 ShutdownNotifierFactory::GetInstance()->Get(context
)->Subscribe(
60 base::Bind(&ExtensionMessageFilter::ShutdownOnUIThread
,
61 base::Unretained(this)));
64 void ExtensionMessageFilter::EnsureShutdownNotifierFactoryBuilt() {
65 ShutdownNotifierFactory::GetInstance();
68 ExtensionMessageFilter::~ExtensionMessageFilter() {
69 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
72 void ExtensionMessageFilter::ShutdownOnUIThread() {
73 event_router_
= nullptr;
74 process_manager_
= nullptr;
75 shutdown_notifier_
.reset();
78 void ExtensionMessageFilter::OverrideThreadForMessage(
79 const IPC::Message
& message
,
80 BrowserThread::ID
* thread
) {
81 switch (message
.type()) {
82 case ExtensionHostMsg_AddListener::ID
:
83 case ExtensionHostMsg_RemoveListener::ID
:
84 case ExtensionHostMsg_AddLazyListener::ID
:
85 case ExtensionHostMsg_RemoveLazyListener::ID
:
86 case ExtensionHostMsg_AddFilteredListener::ID
:
87 case ExtensionHostMsg_RemoveFilteredListener::ID
:
88 case ExtensionHostMsg_ShouldSuspendAck::ID
:
89 case ExtensionHostMsg_SuspendAck::ID
:
90 case ExtensionHostMsg_TransferBlobsAck::ID
:
91 *thread
= BrowserThread::UI
;
98 void ExtensionMessageFilter::OnDestruct() const {
99 BrowserThread::DeleteOnUIThread::Destruct(this);
102 bool ExtensionMessageFilter::OnMessageReceived(const IPC::Message
& message
) {
103 // If we have been shut down already, return.
108 IPC_BEGIN_MESSAGE_MAP(ExtensionMessageFilter
, message
)
109 IPC_MESSAGE_HANDLER(ExtensionHostMsg_AddListener
,
110 OnExtensionAddListener
)
111 IPC_MESSAGE_HANDLER(ExtensionHostMsg_RemoveListener
,
112 OnExtensionRemoveListener
)
113 IPC_MESSAGE_HANDLER(ExtensionHostMsg_AddLazyListener
,
114 OnExtensionAddLazyListener
)
115 IPC_MESSAGE_HANDLER(ExtensionHostMsg_RemoveLazyListener
,
116 OnExtensionRemoveLazyListener
)
117 IPC_MESSAGE_HANDLER(ExtensionHostMsg_AddFilteredListener
,
118 OnExtensionAddFilteredListener
)
119 IPC_MESSAGE_HANDLER(ExtensionHostMsg_RemoveFilteredListener
,
120 OnExtensionRemoveFilteredListener
)
121 IPC_MESSAGE_HANDLER(ExtensionHostMsg_ShouldSuspendAck
,
122 OnExtensionShouldSuspendAck
)
123 IPC_MESSAGE_HANDLER(ExtensionHostMsg_SuspendAck
,
124 OnExtensionSuspendAck
)
125 IPC_MESSAGE_HANDLER(ExtensionHostMsg_TransferBlobsAck
,
126 OnExtensionTransferBlobsAck
)
127 IPC_MESSAGE_UNHANDLED(handled
= false)
128 IPC_END_MESSAGE_MAP()
132 void ExtensionMessageFilter::OnExtensionAddListener(
133 const std::string
& extension_id
,
134 const GURL
& listener_url
,
135 const std::string
& event_name
) {
136 RenderProcessHost
* process
= RenderProcessHost::FromID(render_process_id_
);
143 if (crx_file::id_util::IdIsValid(extension_id
)) {
144 event_router_
->AddEventListener(event_name
, process
, extension_id
);
145 } else if (listener_url
.is_valid()) {
146 event_router_
->AddEventListenerForURL(event_name
, process
, listener_url
);
148 NOTREACHED() << "Tried to add an event listener without a valid "
149 << "extension ID nor listener URL";
153 void ExtensionMessageFilter::OnExtensionRemoveListener(
154 const std::string
& extension_id
,
155 const GURL
& listener_url
,
156 const std::string
& event_name
) {
157 RenderProcessHost
* process
= RenderProcessHost::FromID(render_process_id_
);
164 if (crx_file::id_util::IdIsValid(extension_id
)) {
165 event_router_
->RemoveEventListener(event_name
, process
, extension_id
);
166 } else if (listener_url
.is_valid()) {
167 event_router_
->RemoveEventListenerForURL(event_name
, process
, listener_url
);
169 NOTREACHED() << "Tried to remove an event listener without a valid "
170 << "extension ID nor listener URL";
174 void ExtensionMessageFilter::OnExtensionAddLazyListener(
175 const std::string
& extension_id
, const std::string
& event_name
) {
179 event_router_
->AddLazyEventListener(event_name
, extension_id
);
182 void ExtensionMessageFilter::OnExtensionRemoveLazyListener(
183 const std::string
& extension_id
, const std::string
& event_name
) {
187 event_router_
->RemoveLazyEventListener(event_name
, extension_id
);
190 void ExtensionMessageFilter::OnExtensionAddFilteredListener(
191 const std::string
& extension_id
,
192 const std::string
& event_name
,
193 const base::DictionaryValue
& filter
,
195 RenderProcessHost
* process
= RenderProcessHost::FromID(render_process_id_
);
202 event_router_
->AddFilteredEventListener(event_name
, process
, extension_id
,
206 void ExtensionMessageFilter::OnExtensionRemoveFilteredListener(
207 const std::string
& extension_id
,
208 const std::string
& event_name
,
209 const base::DictionaryValue
& filter
,
211 RenderProcessHost
* process
= RenderProcessHost::FromID(render_process_id_
);
218 event_router_
->RemoveFilteredEventListener(event_name
, process
, extension_id
,
222 void ExtensionMessageFilter::OnExtensionShouldSuspendAck(
223 const std::string
& extension_id
, int sequence_id
) {
224 process_manager_
->OnShouldSuspendAck(extension_id
, sequence_id
);
227 void ExtensionMessageFilter::OnExtensionSuspendAck(
228 const std::string
& extension_id
) {
229 process_manager_
->OnSuspendAck(extension_id
);
232 void ExtensionMessageFilter::OnExtensionTransferBlobsAck(
233 const std::vector
<std::string
>& blob_uuids
) {
234 RenderProcessHost
* process
= RenderProcessHost::FromID(render_process_id_
);
238 BlobHolder::FromRenderProcessHost(process
)->DropBlobs(blob_uuids
);
241 } // namespace extensions