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/extension_system.h"
15 #include "extensions/browser/extension_system_provider.h"
16 #include "extensions/browser/extensions_browser_client.h"
17 #include "extensions/browser/process_manager.h"
18 #include "extensions/browser/process_manager_factory.h"
19 #include "extensions/common/extension.h"
20 #include "extensions/common/extension_messages.h"
21 #include "ipc/ipc_message_macros.h"
23 using content::BrowserThread
;
24 using content::RenderProcessHost
;
26 namespace extensions
{
30 class ShutdownNotifierFactory
31 : public BrowserContextKeyedServiceShutdownNotifierFactory
{
33 static ShutdownNotifierFactory
* GetInstance() {
34 return Singleton
<ShutdownNotifierFactory
>::get();
38 friend struct DefaultSingletonTraits
<ShutdownNotifierFactory
>;
40 ShutdownNotifierFactory()
41 : BrowserContextKeyedServiceShutdownNotifierFactory(
42 "ExtensionMessageFilter") {
43 DependsOn(ExtensionsBrowserClient::Get()->GetExtensionSystemFactory());
44 DependsOn(ProcessManagerFactory::GetInstance());
46 ~ShutdownNotifierFactory() override
{}
48 DISALLOW_COPY_AND_ASSIGN(ShutdownNotifierFactory
);
53 ExtensionMessageFilter::ExtensionMessageFilter(int render_process_id
,
54 content::BrowserContext
* context
)
55 : BrowserMessageFilter(ExtensionMsgStart
),
56 render_process_id_(render_process_id
),
57 extension_system_(ExtensionSystem::Get(context
)),
58 process_manager_(ProcessManager::Get(context
)) {
59 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
61 ShutdownNotifierFactory::GetInstance()->Get(context
)->Subscribe(
62 base::Bind(&ExtensionMessageFilter::ShutdownOnUIThread
,
63 base::Unretained(this)));
66 void ExtensionMessageFilter::EnsureShutdownNotifierFactoryBuilt() {
67 ShutdownNotifierFactory::GetInstance();
70 ExtensionMessageFilter::~ExtensionMessageFilter() {
71 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
74 void ExtensionMessageFilter::ShutdownOnUIThread() {
75 extension_system_
= nullptr;
76 process_manager_
= nullptr;
77 shutdown_notifier_
.reset();
80 void ExtensionMessageFilter::OverrideThreadForMessage(
81 const IPC::Message
& message
,
82 BrowserThread::ID
* thread
) {
83 switch (message
.type()) {
84 case ExtensionHostMsg_AddListener::ID
:
85 case ExtensionHostMsg_RemoveListener::ID
:
86 case ExtensionHostMsg_AddLazyListener::ID
:
87 case ExtensionHostMsg_RemoveLazyListener::ID
:
88 case ExtensionHostMsg_AddFilteredListener::ID
:
89 case ExtensionHostMsg_RemoveFilteredListener::ID
:
90 case ExtensionHostMsg_ShouldSuspendAck::ID
:
91 case ExtensionHostMsg_SuspendAck::ID
:
92 case ExtensionHostMsg_TransferBlobsAck::ID
:
93 *thread
= BrowserThread::UI
;
100 void ExtensionMessageFilter::OnDestruct() const {
101 BrowserThread::DeleteOnUIThread::Destruct(this);
104 bool ExtensionMessageFilter::OnMessageReceived(const IPC::Message
& message
) {
105 // If we have been shut down already, return.
106 if (!extension_system_
)
110 IPC_BEGIN_MESSAGE_MAP(ExtensionMessageFilter
, message
)
111 IPC_MESSAGE_HANDLER(ExtensionHostMsg_AddListener
,
112 OnExtensionAddListener
)
113 IPC_MESSAGE_HANDLER(ExtensionHostMsg_RemoveListener
,
114 OnExtensionRemoveListener
)
115 IPC_MESSAGE_HANDLER(ExtensionHostMsg_AddLazyListener
,
116 OnExtensionAddLazyListener
)
117 IPC_MESSAGE_HANDLER(ExtensionHostMsg_RemoveLazyListener
,
118 OnExtensionRemoveLazyListener
)
119 IPC_MESSAGE_HANDLER(ExtensionHostMsg_AddFilteredListener
,
120 OnExtensionAddFilteredListener
)
121 IPC_MESSAGE_HANDLER(ExtensionHostMsg_RemoveFilteredListener
,
122 OnExtensionRemoveFilteredListener
)
123 IPC_MESSAGE_HANDLER(ExtensionHostMsg_ShouldSuspendAck
,
124 OnExtensionShouldSuspendAck
)
125 IPC_MESSAGE_HANDLER(ExtensionHostMsg_SuspendAck
,
126 OnExtensionSuspendAck
)
127 IPC_MESSAGE_HANDLER(ExtensionHostMsg_TransferBlobsAck
,
128 OnExtensionTransferBlobsAck
)
129 IPC_MESSAGE_UNHANDLED(handled
= false)
130 IPC_END_MESSAGE_MAP()
134 void ExtensionMessageFilter::OnExtensionAddListener(
135 const std::string
& extension_id
,
136 const GURL
& listener_url
,
137 const std::string
& event_name
) {
138 RenderProcessHost
* process
= RenderProcessHost::FromID(render_process_id_
);
142 EventRouter
* router
= extension_system_
->event_router();
146 if (crx_file::id_util::IdIsValid(extension_id
)) {
147 router
->AddEventListener(event_name
, process
, extension_id
);
148 } else if (listener_url
.is_valid()) {
149 router
->AddEventListenerForURL(event_name
, process
, listener_url
);
151 NOTREACHED() << "Tried to add an event listener without a valid "
152 << "extension ID nor listener URL";
156 void ExtensionMessageFilter::OnExtensionRemoveListener(
157 const std::string
& extension_id
,
158 const GURL
& listener_url
,
159 const std::string
& event_name
) {
160 RenderProcessHost
* process
= RenderProcessHost::FromID(render_process_id_
);
164 EventRouter
* router
= extension_system_
->event_router();
168 if (crx_file::id_util::IdIsValid(extension_id
)) {
169 router
->RemoveEventListener(event_name
, process
, extension_id
);
170 } else if (listener_url
.is_valid()) {
171 router
->RemoveEventListenerForURL(event_name
, process
, listener_url
);
173 NOTREACHED() << "Tried to remove an event listener without a valid "
174 << "extension ID nor listener URL";
178 void ExtensionMessageFilter::OnExtensionAddLazyListener(
179 const std::string
& extension_id
, const std::string
& event_name
) {
180 EventRouter
* router
= extension_system_
->event_router();
184 router
->AddLazyEventListener(event_name
, extension_id
);
187 void ExtensionMessageFilter::OnExtensionRemoveLazyListener(
188 const std::string
& extension_id
, const std::string
& event_name
) {
189 EventRouter
* router
= extension_system_
->event_router();
193 router
->RemoveLazyEventListener(event_name
, extension_id
);
196 void ExtensionMessageFilter::OnExtensionAddFilteredListener(
197 const std::string
& extension_id
,
198 const std::string
& event_name
,
199 const base::DictionaryValue
& filter
,
201 RenderProcessHost
* process
= RenderProcessHost::FromID(render_process_id_
);
205 EventRouter
* router
= extension_system_
->event_router();
209 router
->AddFilteredEventListener(
210 event_name
, process
, extension_id
, filter
, lazy
);
213 void ExtensionMessageFilter::OnExtensionRemoveFilteredListener(
214 const std::string
& extension_id
,
215 const std::string
& event_name
,
216 const base::DictionaryValue
& filter
,
218 RenderProcessHost
* process
= RenderProcessHost::FromID(render_process_id_
);
222 EventRouter
* router
= extension_system_
->event_router();
226 router
->RemoveFilteredEventListener(
227 event_name
, process
, extension_id
, filter
, lazy
);
230 void ExtensionMessageFilter::OnExtensionShouldSuspendAck(
231 const std::string
& extension_id
, int sequence_id
) {
232 process_manager_
->OnShouldSuspendAck(extension_id
, sequence_id
);
235 void ExtensionMessageFilter::OnExtensionSuspendAck(
236 const std::string
& extension_id
) {
237 process_manager_
->OnSuspendAck(extension_id
);
240 void ExtensionMessageFilter::OnExtensionTransferBlobsAck(
241 const std::vector
<std::string
>& blob_uuids
) {
242 RenderProcessHost
* process
= RenderProcessHost::FromID(render_process_id_
);
246 BlobHolder::FromRenderProcessHost(process
)->DropBlobs(blob_uuids
);
249 } // namespace extensions