Home | History | Annotate | Download | only in browser
      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