OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/public/browser/browser_message_filter.h" | 5 #include "content/public/browser/browser_message_filter.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
62 if (runner.get()) { | 62 if (runner.get()) { |
63 runner->PostTask( | 63 runner->PostTask( |
64 FROM_HERE, | 64 FROM_HERE, |
65 base::Bind( | 65 base::Bind( |
66 base::IgnoreResult(&Internal::DispatchMessage), this, message)); | 66 base::IgnoreResult(&Internal::DispatchMessage), this, message)); |
67 return true; | 67 return true; |
68 } | 68 } |
69 return DispatchMessage(message); | 69 return DispatchMessage(message); |
70 } | 70 } |
71 | 71 |
72 if (thread == BrowserThread::UI && | |
73 !BrowserMessageFilter::CheckCanDispatchOnUI(message, filter_.get())) { | |
74 return true; | |
75 } | |
76 | |
77 BrowserThread::PostTask( | 72 BrowserThread::PostTask( |
78 thread, FROM_HERE, | 73 thread, FROM_HERE, |
79 base::Bind( | 74 base::Bind( |
80 base::IgnoreResult(&Internal::DispatchMessage), this, message)); | 75 base::IgnoreResult(&Internal::DispatchMessage), this, message)); |
81 return true; | 76 return true; |
82 } | 77 } |
83 | 78 |
84 bool GetSupportedMessageClasses( | 79 bool GetSupportedMessageClasses( |
85 std::vector<uint32_t>* supported_message_classes) const override { | 80 std::vector<uint32_t>* supported_message_classes) const override { |
86 supported_message_classes->assign( | 81 supported_message_classes->assign( |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 | 145 |
151 delete message; | 146 delete message; |
152 return false; | 147 return false; |
153 } | 148 } |
154 | 149 |
155 base::TaskRunner* BrowserMessageFilter::OverrideTaskRunnerForMessage( | 150 base::TaskRunner* BrowserMessageFilter::OverrideTaskRunnerForMessage( |
156 const IPC::Message& message) { | 151 const IPC::Message& message) { |
157 return nullptr; | 152 return nullptr; |
158 } | 153 } |
159 | 154 |
160 bool BrowserMessageFilter::CheckCanDispatchOnUI(const IPC::Message& message, | |
161 IPC::Sender* sender) { | |
162 #if defined(OS_WIN) | |
163 // On Windows there's a potential deadlock with sync messsages going in | |
164 // a circle from browser -> plugin -> renderer -> browser. | |
165 // On Linux we can avoid this by avoiding sync messages from browser->plugin. | |
166 // On Mac we avoid this by not supporting windowed plugins. | |
167 if (message.is_sync() && !message.is_caller_pumping_messages()) { | |
168 // NOTE: IF YOU HIT THIS ASSERT, THE SOLUTION IS ALMOST NEVER TO RUN A | |
169 // NESTED MESSAGE LOOP IN THE RENDERER!!! | |
170 // That introduces reentrancy which causes hard to track bugs. You should | |
171 // find a way to either turn this into an asynchronous message, or one | |
172 // that can be answered on the IO thread. | |
173 NOTREACHED() << "Can't send sync messages to UI thread without pumping " | |
174 "messages in the renderer or else deadlocks can occur if the page " | |
175 "has windowed plugins! (message type " << message.type() << ")"; | |
176 IPC::Message* reply = IPC::SyncMessage::GenerateReply(&message); | |
177 reply->set_reply_error(); | |
178 sender->Send(reply); | |
179 return false; | |
180 } | |
181 #endif | |
182 return true; | |
183 } | |
184 | |
185 void BrowserMessageFilter::ShutdownForBadMessage() { | 155 void BrowserMessageFilter::ShutdownForBadMessage() { |
186 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); | 156 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); |
187 if (command_line->HasSwitch(switches::kDisableKillAfterBadIPC)) | 157 if (command_line->HasSwitch(switches::kDisableKillAfterBadIPC)) |
188 return; | 158 return; |
189 | 159 |
190 BrowserChildProcessHostImpl::HistogramBadMessageTerminated( | 160 BrowserChildProcessHostImpl::HistogramBadMessageTerminated( |
191 PROCESS_TYPE_RENDERER); | 161 PROCESS_TYPE_RENDERER); |
192 | 162 |
193 #if defined(OS_ANDROID) | 163 #if defined(OS_ANDROID) |
194 // Android requires a different approach for killing. | 164 // Android requires a different approach for killing. |
195 StopChildProcess(peer_process_.Handle()); | 165 StopChildProcess(peer_process_.Handle()); |
196 #else | 166 #else |
197 peer_process_.Terminate(content::RESULT_CODE_KILLED_BAD_MESSAGE, false); | 167 peer_process_.Terminate(content::RESULT_CODE_KILLED_BAD_MESSAGE, false); |
198 #endif | 168 #endif |
199 } | 169 } |
200 | 170 |
201 BrowserMessageFilter::~BrowserMessageFilter() { | 171 BrowserMessageFilter::~BrowserMessageFilter() { |
202 } | 172 } |
203 | 173 |
204 IPC::MessageFilter* BrowserMessageFilter::GetFilter() { | 174 IPC::MessageFilter* BrowserMessageFilter::GetFilter() { |
205 // We create this on demand so that if a filter is used in a unit test but | 175 // We create this on demand so that if a filter is used in a unit test but |
206 // never attached to a channel, we don't leak Internal and this; | 176 // never attached to a channel, we don't leak Internal and this; |
207 DCHECK(!internal_) << "Should only be called once."; | 177 DCHECK(!internal_) << "Should only be called once."; |
208 internal_ = new Internal(this); | 178 internal_ = new Internal(this); |
209 return internal_; | 179 return internal_; |
210 } | 180 } |
211 | 181 |
212 } // namespace content | 182 } // namespace content |
OLD | NEW |