Home | History | Annotate | Download | only in renderer_host
      1 // Copyright (c) 2011 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 "chrome/browser/renderer_host/chrome_render_message_filter.h"
      6 
      7 #include "base/file_path.h"
      8 #include "base/metrics/histogram.h"
      9 #include "chrome/browser/browser_process.h"
     10 #include "chrome/browser/extensions/extension_message_service.h"
     11 #include "chrome/browser/metrics/histogram_synchronizer.h"
     12 #include "chrome/browser/nacl_host/nacl_process_host.h"
     13 #include "chrome/browser/net/chrome_url_request_context.h"
     14 #include "chrome/browser/net/predictor_api.h"
     15 #include "chrome/browser/prefs/pref_member.h"
     16 #include "chrome/browser/profiles/profile.h"
     17 #include "chrome/browser/task_manager/task_manager.h"
     18 #include "chrome/common/extensions/extension_file_util.h"
     19 #include "chrome/common/extensions/extension_message_bundle.h"
     20 #include "chrome/common/extensions/extension_messages.h"
     21 #include "chrome/common/pref_names.h"
     22 #include "chrome/common/render_messages.h"
     23 #include "content/browser/renderer_host/resource_dispatcher_host.h"
     24 
     25 #if defined(USE_TCMALLOC)
     26 #include "chrome/browser/browser_about_handler.h"
     27 #endif
     28 
     29 using WebKit::WebCache;
     30 
     31 ChromeRenderMessageFilter::ChromeRenderMessageFilter(
     32     int render_process_id,
     33     Profile* profile,
     34     net::URLRequestContextGetter* request_context)
     35     : render_process_id_(render_process_id),
     36       profile_(profile),
     37       request_context_(request_context) {
     38   allow_outdated_plugins_.Init(prefs::kPluginsAllowOutdated,
     39                                profile_->GetPrefs(), NULL);
     40   allow_outdated_plugins_.MoveToThread(BrowserThread::IO);
     41 }
     42 
     43 ChromeRenderMessageFilter::~ChromeRenderMessageFilter() {
     44 }
     45 
     46 bool ChromeRenderMessageFilter::OnMessageReceived(const IPC::Message& message,
     47                                                   bool* message_was_ok) {
     48   bool handled = true;
     49   IPC_BEGIN_MESSAGE_MAP_EX(ChromeRenderMessageFilter, message, *message_was_ok)
     50     IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_LaunchNaCl, OnLaunchNaCl)
     51     IPC_MESSAGE_HANDLER(ViewHostMsg_DnsPrefetch, OnDnsPrefetch)
     52     IPC_MESSAGE_HANDLER(ViewHostMsg_RendererHistograms, OnRendererHistograms)
     53     IPC_MESSAGE_HANDLER(ViewHostMsg_ResourceTypeStats, OnResourceTypeStats)
     54     IPC_MESSAGE_HANDLER(ViewHostMsg_V8HeapStats, OnV8HeapStats)
     55     IPC_MESSAGE_HANDLER(ExtensionHostMsg_OpenChannelToExtension,
     56                         OnOpenChannelToExtension)
     57     IPC_MESSAGE_HANDLER(ExtensionHostMsg_OpenChannelToTab, OnOpenChannelToTab)
     58     IPC_MESSAGE_HANDLER_DELAY_REPLY(ExtensionHostMsg_GetMessageBundle,
     59                                     OnGetExtensionMessageBundle)
     60 #if defined(USE_TCMALLOC)
     61     IPC_MESSAGE_HANDLER(ViewHostMsg_RendererTcmalloc, OnRendererTcmalloc)
     62 #endif
     63     IPC_MESSAGE_HANDLER(ViewHostMsg_GetOutdatedPluginsPolicy,
     64                         OnGetOutdatedPluginsPolicy)
     65     IPC_MESSAGE_UNHANDLED(handled = false)
     66   IPC_END_MESSAGE_MAP()
     67 
     68   return handled;
     69 }
     70 
     71 void ChromeRenderMessageFilter::OnDestruct() const {
     72   // Destroy on the UI thread because we contain a PrefMember.
     73   BrowserThread::DeleteOnUIThread::Destruct(this);
     74 }
     75 
     76 void ChromeRenderMessageFilter::OverrideThreadForMessage(
     77     const IPC::Message& message, BrowserThread::ID* thread) {
     78   if (message.type() == ViewHostMsg_ResourceTypeStats::ID ||
     79 #if defined(USE_TCMALLOC)
     80       message.type() == ViewHostMsg_RendererTcmalloc::ID ||
     81 #endif
     82       message.type() == ViewHostMsg_ResourceTypeStats::ID) {
     83     *thread = BrowserThread::UI;
     84   }
     85 }
     86 
     87 void ChromeRenderMessageFilter::OnLaunchNaCl(
     88     const std::wstring& url, int channel_descriptor, IPC::Message* reply_msg) {
     89   NaClProcessHost* host = new NaClProcessHost(url);
     90   host->Launch(this, channel_descriptor, reply_msg);
     91 }
     92 
     93 void ChromeRenderMessageFilter::OnDnsPrefetch(
     94     const std::vector<std::string>& hostnames) {
     95   chrome_browser_net::DnsPrefetchList(hostnames);
     96 }
     97 
     98 void ChromeRenderMessageFilter::OnRendererHistograms(
     99     int sequence_number,
    100     const std::vector<std::string>& histograms) {
    101   HistogramSynchronizer::DeserializeHistogramList(sequence_number, histograms);
    102 }
    103 
    104 void ChromeRenderMessageFilter::OnResourceTypeStats(
    105     const WebCache::ResourceTypeStats& stats) {
    106   HISTOGRAM_COUNTS("WebCoreCache.ImagesSizeKB",
    107                    static_cast<int>(stats.images.size / 1024));
    108   HISTOGRAM_COUNTS("WebCoreCache.CSSStylesheetsSizeKB",
    109                    static_cast<int>(stats.cssStyleSheets.size / 1024));
    110   HISTOGRAM_COUNTS("WebCoreCache.ScriptsSizeKB",
    111                    static_cast<int>(stats.scripts.size / 1024));
    112   HISTOGRAM_COUNTS("WebCoreCache.XSLStylesheetsSizeKB",
    113                    static_cast<int>(stats.xslStyleSheets.size / 1024));
    114   HISTOGRAM_COUNTS("WebCoreCache.FontsSizeKB",
    115                    static_cast<int>(stats.fonts.size / 1024));
    116 
    117   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    118   TaskManager::GetInstance()->model()->NotifyResourceTypeStats(
    119       base::GetProcId(peer_handle()), stats);
    120 }
    121 
    122 void ChromeRenderMessageFilter::OnV8HeapStats(int v8_memory_allocated,
    123                                         int v8_memory_used) {
    124   TaskManager::GetInstance()->model()->NotifyV8HeapStats(
    125       base::GetProcId(peer_handle()),
    126       static_cast<size_t>(v8_memory_allocated),
    127       static_cast<size_t>(v8_memory_used));
    128 }
    129 
    130 void ChromeRenderMessageFilter::OnOpenChannelToExtension(
    131     int routing_id, const std::string& source_extension_id,
    132     const std::string& target_extension_id,
    133     const std::string& channel_name, int* port_id) {
    134   int port2_id;
    135   ExtensionMessageService::AllocatePortIdPair(port_id, &port2_id);
    136 
    137   BrowserThread::PostTask(
    138       BrowserThread::UI, FROM_HERE,
    139       NewRunnableMethod(
    140           this, &ChromeRenderMessageFilter::OpenChannelToExtensionOnUIThread,
    141           render_process_id_, routing_id, port2_id, source_extension_id,
    142           target_extension_id, channel_name));
    143 }
    144 
    145 void ChromeRenderMessageFilter::OpenChannelToExtensionOnUIThread(
    146     int source_process_id, int source_routing_id,
    147     int receiver_port_id,
    148     const std::string& source_extension_id,
    149     const std::string& target_extension_id,
    150     const std::string& channel_name) {
    151   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    152   profile_->GetExtensionMessageService()->OpenChannelToExtension(
    153       source_process_id, source_routing_id, receiver_port_id,
    154       source_extension_id, target_extension_id, channel_name);
    155 }
    156 
    157 void ChromeRenderMessageFilter::OnOpenChannelToTab(
    158     int routing_id, int tab_id, const std::string& extension_id,
    159     const std::string& channel_name, int* port_id) {
    160   int port2_id;
    161   ExtensionMessageService::AllocatePortIdPair(port_id, &port2_id);
    162 
    163   BrowserThread::PostTask(
    164       BrowserThread::UI, FROM_HERE,
    165       NewRunnableMethod(
    166           this, &ChromeRenderMessageFilter::OpenChannelToTabOnUIThread,
    167           render_process_id_, routing_id, port2_id, tab_id, extension_id,
    168           channel_name));
    169 }
    170 
    171 void ChromeRenderMessageFilter::OpenChannelToTabOnUIThread(
    172     int source_process_id, int source_routing_id,
    173     int receiver_port_id,
    174     int tab_id,
    175     const std::string& extension_id,
    176     const std::string& channel_name) {
    177   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    178   profile_->GetExtensionMessageService()->OpenChannelToTab(
    179       source_process_id, source_routing_id, receiver_port_id,
    180       tab_id, extension_id, channel_name);
    181 }
    182 
    183 void ChromeRenderMessageFilter::OnGetExtensionMessageBundle(
    184     const std::string& extension_id, IPC::Message* reply_msg) {
    185   ChromeURLRequestContext* context = static_cast<ChromeURLRequestContext*>(
    186     request_context_->GetURLRequestContext());
    187 
    188   FilePath extension_path =
    189       context->extension_info_map()->GetPathForExtension(extension_id);
    190   std::string default_locale =
    191       context->extension_info_map()->GetDefaultLocaleForExtension(extension_id);
    192 
    193   BrowserThread::PostTask(
    194       BrowserThread::FILE, FROM_HERE,
    195       NewRunnableMethod(
    196           this,
    197           &ChromeRenderMessageFilter::OnGetExtensionMessageBundleOnFileThread,
    198           extension_path, extension_id, default_locale, reply_msg));
    199 }
    200 
    201 void ChromeRenderMessageFilter::OnGetExtensionMessageBundleOnFileThread(
    202     const FilePath& extension_path,
    203     const std::string& extension_id,
    204     const std::string& default_locale,
    205     IPC::Message* reply_msg) {
    206   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
    207 
    208   std::map<std::string, std::string> dictionary_map;
    209   if (!default_locale.empty()) {
    210     // Touch disk only if extension is localized.
    211     std::string error;
    212     scoped_ptr<ExtensionMessageBundle> bundle(
    213         extension_file_util::LoadExtensionMessageBundle(
    214             extension_path, default_locale, &error));
    215 
    216     if (bundle.get())
    217       dictionary_map = *bundle->dictionary();
    218   }
    219 
    220   // Add @@extension_id reserved message here, so it's available to
    221   // non-localized extensions too.
    222   dictionary_map.insert(
    223       std::make_pair(ExtensionMessageBundle::kExtensionIdKey, extension_id));
    224 
    225   ExtensionHostMsg_GetMessageBundle::WriteReplyParams(
    226       reply_msg, dictionary_map);
    227   Send(reply_msg);
    228 }
    229 
    230 #if defined(USE_TCMALLOC)
    231 void ChromeRenderMessageFilter::OnRendererTcmalloc(base::ProcessId pid,
    232                                                    const std::string& output) {
    233   AboutTcmallocRendererCallback(pid, output);
    234 }
    235 #endif
    236 
    237 void ChromeRenderMessageFilter::OnGetOutdatedPluginsPolicy(
    238     ContentSetting* policy) {
    239   *policy = CONTENT_SETTING_ALLOW;
    240   if (!allow_outdated_plugins_.GetValue()) {
    241     // If this is false by policy, the plugin is blocked; otherwise, it is
    242     // blocked initially but the user can load it manually.
    243     *policy = allow_outdated_plugins_.IsManaged() ?
    244         CONTENT_SETTING_BLOCK : CONTENT_SETTING_ASK;
    245   }
    246 }
    247