Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(376)

Side by Side Diff: content/browser/browser_message_filter.cc

Issue 6713121: Ensure that BrowserMessageFilter isn't used to process a sync message on the UI thread. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/browser_message_filter.h" 5 #include "content/browser/browser_message_filter.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/process.h" 8 #include "base/process.h"
9 #include "base/process_util.h" 9 #include "base/process_util.h"
10 #include "chrome/browser/metrics/user_metrics.h" 10 #include "chrome/browser/metrics/user_metrics.h"
11 #include "content/common/result_codes.h" 11 #include "content/common/result_codes.h"
12 #include "ipc/ipc_sync_message.h"
12 13
13 BrowserMessageFilter::BrowserMessageFilter() 14 BrowserMessageFilter::BrowserMessageFilter()
14 : channel_(NULL), peer_handle_(base::kNullProcessHandle) { 15 : channel_(NULL), peer_handle_(base::kNullProcessHandle) {
15 } 16 }
16 17
17 BrowserMessageFilter::~BrowserMessageFilter() { 18 BrowserMessageFilter::~BrowserMessageFilter() {
18 base::CloseProcessHandle(peer_handle_); 19 base::CloseProcessHandle(peer_handle_);
19 } 20 }
20 21
21 void BrowserMessageFilter::OnFilterAdded(IPC::Channel* channel) { 22 void BrowserMessageFilter::OnFilterAdded(IPC::Channel* channel) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
60 void BrowserMessageFilter::OverrideThreadForMessage(const IPC::Message& message, 61 void BrowserMessageFilter::OverrideThreadForMessage(const IPC::Message& message,
61 BrowserThread::ID* thread) { 62 BrowserThread::ID* thread) {
62 } 63 }
63 64
64 bool BrowserMessageFilter::OnMessageReceived(const IPC::Message& message) { 65 bool BrowserMessageFilter::OnMessageReceived(const IPC::Message& message) {
65 BrowserThread::ID thread = BrowserThread::IO; 66 BrowserThread::ID thread = BrowserThread::IO;
66 OverrideThreadForMessage(message, &thread); 67 OverrideThreadForMessage(message, &thread);
67 if (thread == BrowserThread::IO) 68 if (thread == BrowserThread::IO)
68 return DispatchMessage(message); 69 return DispatchMessage(message);
69 70
71 if (thread == BrowserThread::UI &&
72 !MessageCanBeDispatchedOnUI(message, this)) {
73 return true;
74 }
75
70 BrowserThread::PostTask( 76 BrowserThread::PostTask(
71 thread, FROM_HERE, 77 thread, FROM_HERE,
72 NewRunnableMethod( 78 NewRunnableMethod(
73 this, &BrowserMessageFilter::DispatchMessage, message)); 79 this, &BrowserMessageFilter::DispatchMessage, message));
74 return true; 80 return true;
75 } 81 }
76 82
77 bool BrowserMessageFilter::DispatchMessage(const IPC::Message& message) { 83 bool BrowserMessageFilter::DispatchMessage(const IPC::Message& message) {
78 bool message_was_ok = true; 84 bool message_was_ok = true;
79 bool rv = OnMessageReceived(message, &message_was_ok); 85 bool rv = OnMessageReceived(message, &message_was_ok);
80 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO) || rv) << 86 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO) || rv) <<
81 "Must handle messages that were dispatched to another thread!"; 87 "Must handle messages that were dispatched to another thread!";
82 if (!message_was_ok) { 88 if (!message_was_ok) {
83 UserMetrics::RecordAction(UserMetricsAction("BadMessageTerminate_BMF")); 89 UserMetrics::RecordAction(UserMetricsAction("BadMessageTerminate_BMF"));
84 BadMessageReceived(); 90 BadMessageReceived();
85 } 91 }
86 92
87 return rv; 93 return rv;
88 } 94 }
89 95
90 void BrowserMessageFilter::BadMessageReceived() { 96 void BrowserMessageFilter::BadMessageReceived() {
91 base::KillProcess(peer_handle(), ResultCodes::KILLED_BAD_MESSAGE, false); 97 base::KillProcess(peer_handle(), ResultCodes::KILLED_BAD_MESSAGE, false);
92 } 98 }
99
100 bool BrowserMessageFilter::MessageCanBeDispatchedOnUI(
101 const IPC::Message& message, IPC::Message::Sender* sender) {
102 #if defined(OS_WIN)
103 // On Windows there's a potential deadlock with sync messsages going in
104 // a circle from browser -> plugin -> renderer -> browser.
105 // On Linux we can avoid this by avoiding sync messages from browser->plugin.
106 // On Mac we avoid this by not supporting windowed plugins.
107 if (message.is_sync() && !message.is_caller_pumping_messages()) {
108 // NOTE: IF YOU HIT THIS ASSERT, THE SOLUTION IS ALMOST NEVER TO RUN A
109 // NESTED MESSAGE LOOP IN THE RENDERER!!!
110 // That introduces reentrancy which causes hard to track bugs. You should
111 // find a way to either turn this into an asynchronous message, or one
112 // that can be answered on the IO thread.
113 NOTREACHED() << "Can't send sync messages to UI thread without pumping "
114 "messages in the renderer or else deadlocks can occur if the page "
115 "has windowed plugins! (message type " << message.type() << ")";
116 IPC::Message* reply = IPC::SyncMessage::GenerateReply(&message);
117 reply->set_reply_error();
118 sender->Send(reply);
119 return false;
120 }
121 #endif
122 return true;
123 }
OLDNEW
« no previous file with comments | « content/browser/browser_message_filter.h ('k') | content/browser/renderer_host/render_view_host.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698