Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / extensions / browser / extension_message_filter.cc
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.
4
5 #include "extensions/browser/extension_message_filter.h"
6
7 #include "components/crx_file/id_util.h"
8 #include "content/public/browser/browser_thread.h"
9 #include "content/public/browser/render_frame_host.h"
10 #include "content/public/browser/render_process_host.h"
11 #include "content/public/browser/render_view_host.h"
12 #include "content/public/browser/resource_dispatcher_host.h"
13 #include "extensions/browser/blob_holder.h"
14 #include "extensions/browser/event_router.h"
15 #include "extensions/browser/extension_function_dispatcher.h"
16 #include "extensions/browser/extension_system.h"
17 #include "extensions/browser/guest_view/guest_view_base.h"
18 #include "extensions/browser/guest_view/guest_view_manager.h"
19 #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_constants.h"
20 #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
21 #include "extensions/browser/info_map.h"
22 #include "extensions/browser/process_manager.h"
23 #include "extensions/common/extension.h"
24 #include "extensions/common/extension_messages.h"
25 #include "ipc/ipc_message_macros.h"
26
27 using content::BrowserThread;
28 using content::RenderProcessHost;
29
30 namespace extensions {
31
32 ExtensionMessageFilter::ExtensionMessageFilter(int render_process_id,
33                                                content::BrowserContext* context)
34     : BrowserMessageFilter(ExtensionMsgStart),
35       render_process_id_(render_process_id),
36       browser_context_(context),
37       extension_info_map_(ExtensionSystem::Get(context)->info_map()),
38       weak_ptr_factory_(this) {
39   DCHECK_CURRENTLY_ON(BrowserThread::UI);
40 }
41
42 ExtensionMessageFilter::~ExtensionMessageFilter() {
43   DCHECK_CURRENTLY_ON(BrowserThread::IO);
44 }
45
46 void ExtensionMessageFilter::OverrideThreadForMessage(
47     const IPC::Message& message,
48     BrowserThread::ID* thread) {
49   switch (message.type()) {
50     case ExtensionHostMsg_AddListener::ID:
51     case ExtensionHostMsg_AttachGuest::ID:
52     case ExtensionHostMsg_RemoveListener::ID:
53     case ExtensionHostMsg_AddLazyListener::ID:
54     case ExtensionHostMsg_CreateMimeHandlerViewGuest::ID:
55     case ExtensionHostMsg_RemoveLazyListener::ID:
56     case ExtensionHostMsg_AddFilteredListener::ID:
57     case ExtensionHostMsg_RemoveFilteredListener::ID:
58     case ExtensionHostMsg_ShouldSuspendAck::ID:
59     case ExtensionHostMsg_SuspendAck::ID:
60     case ExtensionHostMsg_TransferBlobsAck::ID:
61       *thread = BrowserThread::UI;
62       break;
63     default:
64       break;
65   }
66 }
67
68 void ExtensionMessageFilter::OnDestruct() const {
69   // Destroy the filter on the IO thread since that's where its weak pointers
70   // are being used.
71   BrowserThread::DeleteOnIOThread::Destruct(this);
72 }
73
74 bool ExtensionMessageFilter::OnMessageReceived(const IPC::Message& message) {
75   bool handled = true;
76   IPC_BEGIN_MESSAGE_MAP(ExtensionMessageFilter, message)
77     IPC_MESSAGE_HANDLER(ExtensionHostMsg_AddListener,
78                         OnExtensionAddListener)
79     IPC_MESSAGE_HANDLER(ExtensionHostMsg_RemoveListener,
80                         OnExtensionRemoveListener)
81     IPC_MESSAGE_HANDLER(ExtensionHostMsg_AddLazyListener,
82                         OnExtensionAddLazyListener)
83     IPC_MESSAGE_HANDLER(ExtensionHostMsg_AttachGuest,
84                         OnExtensionAttachGuest)
85     IPC_MESSAGE_HANDLER(ExtensionHostMsg_CreateMimeHandlerViewGuest,
86                         OnExtensionCreateMimeHandlerViewGuest)
87     IPC_MESSAGE_HANDLER(ExtensionHostMsg_RemoveLazyListener,
88                         OnExtensionRemoveLazyListener)
89     IPC_MESSAGE_HANDLER(ExtensionHostMsg_AddFilteredListener,
90                         OnExtensionAddFilteredListener)
91     IPC_MESSAGE_HANDLER(ExtensionHostMsg_RemoveFilteredListener,
92                         OnExtensionRemoveFilteredListener)
93     IPC_MESSAGE_HANDLER(ExtensionHostMsg_ShouldSuspendAck,
94                         OnExtensionShouldSuspendAck)
95     IPC_MESSAGE_HANDLER(ExtensionHostMsg_SuspendAck,
96                         OnExtensionSuspendAck)
97     IPC_MESSAGE_HANDLER(ExtensionHostMsg_TransferBlobsAck,
98                         OnExtensionTransferBlobsAck)
99     IPC_MESSAGE_HANDLER(ExtensionHostMsg_GenerateUniqueID,
100                         OnExtensionGenerateUniqueID)
101     IPC_MESSAGE_HANDLER(ExtensionHostMsg_ResumeRequests,
102                         OnExtensionResumeRequests);
103     IPC_MESSAGE_HANDLER(ExtensionHostMsg_RequestForIOThread,
104                         OnExtensionRequestForIOThread)
105     IPC_MESSAGE_UNHANDLED(handled = false)
106   IPC_END_MESSAGE_MAP()
107   return handled;
108 }
109
110 void ExtensionMessageFilter::OnExtensionAddListener(
111     const std::string& extension_id,
112     const GURL& listener_url,
113     const std::string& event_name) {
114   RenderProcessHost* process = RenderProcessHost::FromID(render_process_id_);
115   if (!process)
116     return;
117   EventRouter* router = EventRouter::Get(browser_context_);
118   if (!router)
119     return;
120
121   if (crx_file::id_util::IdIsValid(extension_id)) {
122     router->AddEventListener(event_name, process, extension_id);
123   } else if (listener_url.is_valid()) {
124     router->AddEventListenerForURL(event_name, process, listener_url);
125   } else {
126     NOTREACHED() << "Tried to add an event listener without a valid "
127                  << "extension ID nor listener URL";
128   }
129 }
130
131 void ExtensionMessageFilter::OnExtensionRemoveListener(
132     const std::string& extension_id,
133     const GURL& listener_url,
134     const std::string& event_name) {
135   RenderProcessHost* process = RenderProcessHost::FromID(render_process_id_);
136   if (!process)
137     return;
138   EventRouter* router = EventRouter::Get(browser_context_);
139   if (!router)
140     return;
141
142   if (crx_file::id_util::IdIsValid(extension_id)) {
143     router->RemoveEventListener(event_name, process, extension_id);
144   } else if (listener_url.is_valid()) {
145     router->RemoveEventListenerForURL(event_name, process, listener_url);
146   } else {
147     NOTREACHED() << "Tried to remove an event listener without a valid "
148                  << "extension ID nor listener URL";
149   }
150 }
151
152 void ExtensionMessageFilter::OnExtensionAddLazyListener(
153     const std::string& extension_id, const std::string& event_name) {
154   EventRouter* router = EventRouter::Get(browser_context_);
155   if (!router)
156     return;
157   router->AddLazyEventListener(event_name, extension_id);
158 }
159
160 void ExtensionMessageFilter::OnExtensionAttachGuest(
161     int routing_id,
162     int element_instance_id,
163     int guest_instance_id,
164     const base::DictionaryValue& params) {
165   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
166   GuestViewManager* manager =
167       GuestViewManager::FromBrowserContext(browser_context_);
168   if (!manager)
169     return;
170
171   manager->AttachGuest(render_process_id_,
172                        routing_id,
173                        element_instance_id,
174                        guest_instance_id,
175                        params);
176 }
177
178 void ExtensionMessageFilter::OnExtensionCreateMimeHandlerViewGuest(
179     int render_frame_id,
180     const std::string& src,
181     const std::string& mime_type,
182     int element_instance_id) {
183   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
184   GuestViewManager* manager =
185       GuestViewManager::FromBrowserContext(browser_context_);
186   if (!manager)
187     return;
188
189   content::RenderFrameHost* rfh =
190       content::RenderFrameHost::FromID(render_process_id_, render_frame_id);
191   content::WebContents* embedder_web_contents =
192       content::WebContents::FromRenderFrameHost(rfh);
193   if (!embedder_web_contents)
194     return;
195
196   GuestViewManager::WebContentsCreatedCallback callback =
197       base::Bind(&ExtensionMessageFilter::MimeHandlerViewGuestCreatedCallback,
198                  this,
199                  element_instance_id,
200                  render_process_id_,
201                  render_frame_id,
202                  src);
203   base::DictionaryValue create_params;
204   create_params.SetString(mime_handler_view::kMimeType, mime_type);
205   create_params.SetString(mime_handler_view::kSrc, src);
206   manager->CreateGuest(MimeHandlerViewGuest::Type,
207                        "",
208                        embedder_web_contents,
209                        create_params,
210                        callback);
211 }
212
213 void ExtensionMessageFilter::OnExtensionRemoveLazyListener(
214     const std::string& extension_id, const std::string& event_name) {
215   EventRouter* router = EventRouter::Get(browser_context_);
216   if (!router)
217     return;
218   router->RemoveLazyEventListener(event_name, extension_id);
219 }
220
221 void ExtensionMessageFilter::OnExtensionAddFilteredListener(
222     const std::string& extension_id,
223     const std::string& event_name,
224     const base::DictionaryValue& filter,
225     bool lazy) {
226   RenderProcessHost* process = RenderProcessHost::FromID(render_process_id_);
227   if (!process)
228     return;
229   EventRouter* router = EventRouter::Get(browser_context_);
230   if (!router)
231     return;
232   router->AddFilteredEventListener(
233       event_name, process, extension_id, filter, lazy);
234 }
235
236 void ExtensionMessageFilter::OnExtensionRemoveFilteredListener(
237     const std::string& extension_id,
238     const std::string& event_name,
239     const base::DictionaryValue& filter,
240     bool lazy) {
241   RenderProcessHost* process = RenderProcessHost::FromID(render_process_id_);
242   if (!process)
243     return;
244   EventRouter* router = EventRouter::Get(browser_context_);
245   if (!router)
246     return;
247   router->RemoveFilteredEventListener(
248       event_name, process, extension_id, filter, lazy);
249 }
250
251 void ExtensionMessageFilter::OnExtensionShouldSuspendAck(
252      const std::string& extension_id, int sequence_id) {
253   ProcessManager::Get(browser_context_)
254       ->OnShouldSuspendAck(extension_id, sequence_id);
255 }
256
257 void ExtensionMessageFilter::OnExtensionSuspendAck(
258      const std::string& extension_id) {
259   ProcessManager::Get(browser_context_)->OnSuspendAck(extension_id);
260 }
261
262 void ExtensionMessageFilter::OnExtensionTransferBlobsAck(
263     const std::vector<std::string>& blob_uuids) {
264   RenderProcessHost* process = RenderProcessHost::FromID(render_process_id_);
265   if (!process)
266     return;
267   BlobHolder::FromRenderProcessHost(process)->DropBlobs(blob_uuids);
268 }
269
270 void ExtensionMessageFilter::OnExtensionGenerateUniqueID(int* unique_id) {
271   static int next_unique_id = 0;
272   *unique_id = ++next_unique_id;
273 }
274
275 void ExtensionMessageFilter::OnExtensionResumeRequests(int route_id) {
276   content::ResourceDispatcherHost::Get()->ResumeBlockedRequestsForRoute(
277       render_process_id_, route_id);
278 }
279
280 void ExtensionMessageFilter::OnExtensionRequestForIOThread(
281     int routing_id,
282     const ExtensionHostMsg_Request_Params& params) {
283   DCHECK_CURRENTLY_ON(BrowserThread::IO);
284   ExtensionFunctionDispatcher::DispatchOnIOThread(
285       extension_info_map_.get(),
286       browser_context_,
287       render_process_id_,
288       weak_ptr_factory_.GetWeakPtr(),
289       routing_id,
290       params);
291 }
292
293 void ExtensionMessageFilter::MimeHandlerViewGuestCreatedCallback(
294     int element_instance_id,
295     int embedder_render_process_id,
296     int embedder_render_frame_id,
297     const std::string& src,
298     content::WebContents* web_contents) {
299   GuestViewManager* manager =
300       GuestViewManager::FromBrowserContext(browser_context_);
301   if (!manager)
302     return;
303
304   MimeHandlerViewGuest* guest_view =
305       MimeHandlerViewGuest::FromWebContents(web_contents);
306   if (!guest_view)
307     return;
308   int guest_instance_id = guest_view->guest_instance_id();
309
310   content::RenderFrameHost* rfh = content::RenderFrameHost::FromID(
311       embedder_render_process_id, embedder_render_frame_id);
312   if (!rfh)
313     return;
314
315   base::DictionaryValue attach_params;
316   attach_params.SetString(mime_handler_view::kSrc, src);
317   manager->AttachGuest(embedder_render_process_id,
318                        rfh->GetRenderViewHost()->GetRoutingID(),
319                        element_instance_id,
320                        guest_instance_id,
321                        attach_params);
322
323   IPC::Message* msg =
324       new ExtensionMsg_CreateMimeHandlerViewGuestACK(element_instance_id);
325   msg->set_routing_id(rfh->GetRoutingID());
326   rfh->Send(msg);
327 }
328
329 }  // namespace extensions