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* process_manager = 254 ExtensionSystem::Get(browser_context_)->process_manager(); 255 if (process_manager) 256 process_manager->OnShouldSuspendAck(extension_id, sequence_id); 257 } 258 259 void ExtensionMessageFilter::OnExtensionSuspendAck( 260 const std::string& extension_id) { 261 ProcessManager* process_manager = 262 ExtensionSystem::Get(browser_context_)->process_manager(); 263 if (process_manager) 264 process_manager->OnSuspendAck(extension_id); 265 } 266 267 void ExtensionMessageFilter::OnExtensionTransferBlobsAck( 268 const std::vector<std::string>& blob_uuids) { 269 RenderProcessHost* process = RenderProcessHost::FromID(render_process_id_); 270 if (!process) 271 return; 272 BlobHolder::FromRenderProcessHost(process)->DropBlobs(blob_uuids); 273 } 274 275 void ExtensionMessageFilter::OnExtensionGenerateUniqueID(int* unique_id) { 276 static int next_unique_id = 0; 277 *unique_id = ++next_unique_id; 278 } 279 280 void ExtensionMessageFilter::OnExtensionResumeRequests(int route_id) { 281 content::ResourceDispatcherHost::Get()->ResumeBlockedRequestsForRoute( 282 render_process_id_, route_id); 283 } 284 285 void ExtensionMessageFilter::OnExtensionRequestForIOThread( 286 int routing_id, 287 const ExtensionHostMsg_Request_Params& params) { 288 DCHECK_CURRENTLY_ON(BrowserThread::IO); 289 ExtensionFunctionDispatcher::DispatchOnIOThread( 290 extension_info_map_.get(), 291 browser_context_, 292 render_process_id_, 293 weak_ptr_factory_.GetWeakPtr(), 294 routing_id, 295 params); 296 } 297 298 void ExtensionMessageFilter::MimeHandlerViewGuestCreatedCallback( 299 int element_instance_id, 300 int embedder_render_process_id, 301 int embedder_render_frame_id, 302 const std::string& src, 303 content::WebContents* web_contents) { 304 GuestViewManager* manager = 305 GuestViewManager::FromBrowserContext(browser_context_); 306 if (!manager) 307 return; 308 309 MimeHandlerViewGuest* guest_view = 310 MimeHandlerViewGuest::FromWebContents(web_contents); 311 if (!guest_view) 312 return; 313 int guest_instance_id = guest_view->guest_instance_id(); 314 315 content::RenderFrameHost* rfh = content::RenderFrameHost::FromID( 316 embedder_render_process_id, embedder_render_frame_id); 317 if (!rfh) 318 return; 319 320 base::DictionaryValue attach_params; 321 attach_params.SetString(mime_handler_view::kSrc, src); 322 manager->AttachGuest(embedder_render_process_id, 323 rfh->GetRenderViewHost()->GetRoutingID(), 324 element_instance_id, 325 guest_instance_id, 326 attach_params); 327 328 IPC::Message* msg = 329 new ExtensionMsg_CreateMimeHandlerViewGuestACK(element_instance_id); 330 msg->set_routing_id(rfh->GetRoutingID()); 331 rfh->Send(msg); 332 } 333 334 } // namespace extensions 335