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