15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_message_filter.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 1058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch#include "base/process/kill.h" 1158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch#include "base/process/process_handle.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/task_runner.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/user_metrics.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/result_codes.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_sync_message.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserMessageFilter; 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content { 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BrowserMessageFilter::BrowserMessageFilter() 227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch : channel_(NULL), 237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#if defined(OS_WIN) 247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch peer_handle_(base::kNullProcessHandle), 257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#endif 267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch peer_pid_(base::kNullProcessId) { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserMessageFilter::OnFilterAdded(IPC::Channel* channel) { 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) channel_ = channel; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserMessageFilter::OnChannelClosing() { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) channel_ = NULL; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserMessageFilter::OnChannelConnected(int32 peer_pid) { 387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch peer_pid_ = peer_pid; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserMessageFilter::OnMessageReceived(const IPC::Message& message) { 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::ID thread = BrowserThread::IO; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OverrideThreadForMessage(message, &thread); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (thread == BrowserThread::IO) { 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<base::TaskRunner> runner = 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OverrideTaskRunnerForMessage(message); 48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (runner.get()) { 49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) runner->PostTask( 50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) FROM_HERE, 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(base::IgnoreResult(&BrowserMessageFilter::DispatchMessage), 52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) this, 53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) message)); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DispatchMessage(message); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (thread == BrowserThread::UI && !CheckCanDispatchOnUI(message, this)) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thread, FROM_HERE, 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(base::IgnoreResult(&BrowserMessageFilter::DispatchMessage), 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, message)); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbase::ProcessHandle BrowserMessageFilter::PeerHandle() { 707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#if defined(OS_WIN) 717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::AutoLock lock(peer_handle_lock_); 727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (peer_handle_ == base::kNullProcessHandle) 737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::OpenPrivilegedProcessHandle(peer_pid_, &peer_handle_); 747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return peer_handle_; 767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#else 777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::ProcessHandle result = base::kNullProcessHandle; 787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::OpenPrivilegedProcessHandle(peer_pid_, &result); 797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return result; 807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#endif 817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserMessageFilter::Send(IPC::Message* message) { 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (message->is_sync()) { 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't support sending synchronous messages from the browser. If we 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // really needed it, we can make this class derive from SyncMessageFilter 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // but it seems better to not allow sending synchronous messages from the 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // browser, since it might allow a corrupt/malicious renderer to hang us. 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Can't send sync message through BrowserMessageFilter!"; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::IO, 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(base::IgnoreResult(&BrowserMessageFilter::Send), this, 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message)); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (channel_) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return channel_->Send(message); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete message; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserMessageFilter::OverrideThreadForMessage(const IPC::Message& message, 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::ID* thread) { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::TaskRunner* BrowserMessageFilter::OverrideTaskRunnerForMessage( 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const IPC::Message& message) { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserMessageFilter::CheckCanDispatchOnUI(const IPC::Message& message, 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC::Sender* sender) { 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // On Windows there's a potential deadlock with sync messsages going in 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a circle from browser -> plugin -> renderer -> browser. 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // On Linux we can avoid this by avoiding sync messages from browser->plugin. 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // On Mac we avoid this by not supporting windowed plugins. 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (message.is_sync() && !message.is_caller_pumping_messages()) { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: IF YOU HIT THIS ASSERT, THE SOLUTION IS ALMOST NEVER TO RUN A 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NESTED MESSAGE LOOP IN THE RENDERER!!! 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // That introduces reentrancy which causes hard to track bugs. You should 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // find a way to either turn this into an asynchronous message, or one 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that can be answered on the IO thread. 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Can't send sync messages to UI thread without pumping " 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "messages in the renderer or else deadlocks can occur if the page " 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "has windowed plugins! (message type " << message.type() << ")"; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC::Message* reply = IPC::SyncMessage::GenerateReply(&message); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reply->set_reply_error(); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sender->Send(reply); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserMessageFilter::BadMessageReceived() { 1447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::KillProcess(PeerHandle(), content::RESULT_CODE_KILLED_BAD_MESSAGE, 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BrowserMessageFilter::~BrowserMessageFilter() { 1497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#if defined(OS_WIN) 1507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (peer_handle_ != base::kNullProcessHandle) 1517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::CloseProcessHandle(peer_handle_); 1527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#endif 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserMessageFilter::DispatchMessage(const IPC::Message& message) { 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool message_was_ok = true; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool rv = OnMessageReceived(message, &message_was_ok); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO) || rv) << 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Must handle messages that were dispatched to another thread!"; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!message_was_ok) { 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RecordAction(UserMetricsAction("BadMessageTerminate_BMF")); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BadMessageReceived(); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace content 169