Chromium Code Reviews| 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 "chrome/browser/ui/hung_plugin_tab_helper.h" | 5 #include "chrome/browser/ui/hung_plugin_tab_helper.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/memory/scoped_ptr.h" | |
| 9 #include "base/process.h" | |
| 8 #include "base/process_util.h" | 10 #include "base/process_util.h" |
| 11 #include "base/rand_util.h" | |
| 9 #include "build/build_config.h" | 12 #include "build/build_config.h" |
| 10 #include "chrome/browser/api/infobars/confirm_infobar_delegate.h" | 13 #include "chrome/browser/api/infobars/confirm_infobar_delegate.h" |
| 11 #include "chrome/browser/infobars/infobar.h" | 14 #include "chrome/browser/infobars/infobar.h" |
| 12 #include "chrome/browser/infobars/infobar_tab_helper.h" | 15 #include "chrome/browser/infobars/infobar_tab_helper.h" |
| 13 #include "chrome/browser/ui/tab_contents/tab_contents.h" | 16 #include "chrome/browser/ui/tab_contents/tab_contents.h" |
| 14 #include "chrome/common/chrome_notification_types.h" | 17 #include "chrome/common/chrome_notification_types.h" |
| 18 #include "chrome/common/chrome_version_info.h" | |
| 15 #include "content/public/browser/browser_child_process_host_iterator.h" | 19 #include "content/public/browser/browser_child_process_host_iterator.h" |
| 16 #include "content/public/browser/browser_thread.h" | 20 #include "content/public/browser/browser_thread.h" |
| 17 #include "content/public/browser/child_process_data.h" | 21 #include "content/public/browser/child_process_data.h" |
| 18 #include "content/public/browser/notification_details.h" | 22 #include "content/public/browser/notification_details.h" |
| 19 #include "content/public/browser/notification_service.h" | 23 #include "content/public/browser/notification_service.h" |
| 20 #include "content/public/browser/plugin_service.h" | 24 #include "content/public/browser/plugin_service.h" |
| 25 #include "content/public/browser/render_process_host.h" | |
| 21 #include "content/public/common/result_codes.h" | 26 #include "content/public/common/result_codes.h" |
| 22 #include "grit/chromium_strings.h" | 27 #include "grit/chromium_strings.h" |
| 23 #include "grit/generated_resources.h" | 28 #include "grit/generated_resources.h" |
| 24 #include "grit/locale_settings.h" | 29 #include "grit/locale_settings.h" |
| 25 #include "grit/theme_resources.h" | 30 #include "grit/theme_resources.h" |
| 26 #include "ui/base/l10n/l10n_util.h" | 31 #include "ui/base/l10n/l10n_util.h" |
| 27 #include "ui/base/resource/resource_bundle.h" | 32 #include "ui/base/resource/resource_bundle.h" |
| 28 | 33 |
| 29 #if defined(OS_WIN) | 34 #if defined(OS_WIN) |
| 30 #include "chrome/browser/hang_monitor/hang_crash_dump_win.h" | 35 #include "chrome/browser/hang_monitor/hang_crash_dump_win.h" |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 55 base::KillProcess(data.handle, content::RESULT_CODE_HUNG, false); | 60 base::KillProcess(data.handle, content::RESULT_CODE_HUNG, false); |
| 56 #endif | 61 #endif |
| 57 break; | 62 break; |
| 58 } | 63 } |
| 59 ++iter; | 64 ++iter; |
| 60 } | 65 } |
| 61 // Ignore the case where we didn't find the plugin, it may have terminated | 66 // Ignore the case where we didn't find the plugin, it may have terminated |
| 62 // before this function could run. | 67 // before this function could run. |
| 63 } | 68 } |
| 64 | 69 |
| 70 #if defined(OS_WIN) | |
| 71 class OwnedHandleVector { | |
| 72 public: | |
| 73 OwnedHandleVector() {} | |
| 74 | |
| 75 ~OwnedHandleVector() { | |
| 76 for (std::vector<HANDLE>::const_iterator iter = data_.begin(); | |
| 77 iter != data_.end(); ++iter) { | |
| 78 ::CloseHandle(*iter); | |
| 79 } | |
| 80 } | |
| 81 | |
| 82 std::vector<HANDLE>& data() { return data_; } | |
| 83 | |
| 84 private: | |
| 85 std::vector<HANDLE> data_; | |
| 86 | |
| 87 DISALLOW_COPY_AND_ASSIGN(OwnedHandleVector); | |
| 88 }; | |
| 89 | |
| 90 void DumpRenderersOnIOThread(OwnedHandleVector* renderer_handles) { | |
| 91 for (std::vector<HANDLE>::const_iterator iter = | |
| 92 renderer_handles->data().begin(); | |
| 93 iter != renderer_handles->data().end(); ++iter) { | |
| 94 CrashDumpIfProcessHandlingPepper(*iter); | |
| 95 } | |
| 96 } | |
| 97 #endif | |
| 98 | |
| 65 } // namespace | 99 } // namespace |
| 66 | 100 |
| 67 class HungPluginTabHelper::InfoBarDelegate : public ConfirmInfoBarDelegate { | 101 class HungPluginTabHelper::InfoBarDelegate : public ConfirmInfoBarDelegate { |
| 68 public: | 102 public: |
| 69 InfoBarDelegate(HungPluginTabHelper* helper, | 103 InfoBarDelegate(HungPluginTabHelper* helper, |
| 70 InfoBarTabHelper* infobar_helper, | 104 InfoBarTabHelper* infobar_helper, |
| 71 int plugin_child_id, | 105 int plugin_child_id, |
| 72 const string16& plugin_name); | 106 const string16& plugin_name); |
| 73 virtual ~InfoBarDelegate(); | 107 virtual ~InfoBarDelegate(); |
| 74 | 108 |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 231 i->first)); | 265 i->first)); |
| 232 | 266 |
| 233 // Next time we do this, delay it twice as long to avoid being annoying. | 267 // Next time we do this, delay it twice as long to avoid being annoying. |
| 234 state->next_reshow_delay *= 2; | 268 state->next_reshow_delay *= 2; |
| 235 return; | 269 return; |
| 236 } | 270 } |
| 237 } | 271 } |
| 238 } | 272 } |
| 239 | 273 |
| 240 void HungPluginTabHelper::KillPlugin(int child_id) { | 274 void HungPluginTabHelper::KillPlugin(int child_id) { |
| 275 #if defined(OS_WIN) | |
| 276 // Dump renderers that are sending or receiving pepper messages, in order to | |
| 277 // diagnose inter-process deadlocks. | |
| 278 // Only do that on the Canary channel, for 20% of pepper plugin hangs. | |
| 279 if (base::RandInt(0, 100) < 20) { | |
| 280 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel(); | |
| 281 if (channel == chrome::VersionInfo::CHANNEL_CANARY) { | |
| 282 scoped_ptr<OwnedHandleVector> renderer_handles(new OwnedHandleVector); | |
| 283 HANDLE current_process = ::GetCurrentProcess(); | |
| 284 content::RenderProcessHost::iterator renderer_iter = | |
| 285 content::RenderProcessHost::AllHostsIterator(); | |
| 286 for (; !renderer_iter.IsAtEnd(); renderer_iter.Advance()) { | |
| 287 content::RenderProcessHost* host = renderer_iter.GetCurrentValue(); | |
| 288 HANDLE handle = NULL; | |
| 289 ::DuplicateHandle(current_process, host->GetHandle(), current_process, | |
| 290 &handle, 0, FALSE, DUPLICATE_SAME_ACCESS); | |
| 291 renderer_handles->data().push_back(handle); | |
| 292 } | |
| 293 // If there are a lot of renderer processes, it is likely that we will | |
| 294 // generate too many crash dumps. They might not all be uploaded/recorded | |
| 295 // due to our crash dump uploading restrictions. So we just don't generate | |
| 296 // renderer crash dumps in that case. | |
| 297 if (renderer_handles->data().size() > 0 && | |
| 298 renderer_handles->data().size() < 8) { | |
| 299 content::BrowserThread::PostTask( | |
|
eroman
2012/09/17 19:23:48
Why is it necessary to duplicate the handles, and
yzshen1
2012/09/17 20:11:03
The reasons why I did it this way:
- I know that w
| |
| 300 content::BrowserThread::IO, FROM_HERE, | |
| 301 base::Bind(&DumpRenderersOnIOThread, | |
| 302 base::Owned(renderer_handles.release()))); | |
| 303 } | |
| 304 } | |
| 305 } | |
| 306 #endif | |
| 307 | |
| 241 PluginStateMap::iterator found = hung_plugins_.find(child_id); | 308 PluginStateMap::iterator found = hung_plugins_.find(child_id); |
| 242 if (found == hung_plugins_.end()) { | 309 if (found == hung_plugins_.end()) { |
| 243 NOTREACHED(); | 310 NOTREACHED(); |
| 244 return; | 311 return; |
| 245 } | 312 } |
| 246 | 313 |
| 247 content::BrowserThread::PostTask(content::BrowserThread::IO, | 314 content::BrowserThread::PostTask(content::BrowserThread::IO, |
| 248 FROM_HERE, | 315 FROM_HERE, |
| 249 base::Bind(&KillPluginOnIOThread, child_id)); | 316 base::Bind(&KillPluginOnIOThread, child_id)); |
| 250 CloseBar(found->second.get()); | 317 CloseBar(found->second.get()); |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 281 state->info_bar = NULL; | 348 state->info_bar = NULL; |
| 282 } | 349 } |
| 283 } | 350 } |
| 284 | 351 |
| 285 InfoBarTabHelper* HungPluginTabHelper::GetInfoBarHelper() { | 352 InfoBarTabHelper* HungPluginTabHelper::GetInfoBarHelper() { |
| 286 TabContents* tab_contents = TabContents::FromWebContents(web_contents()); | 353 TabContents* tab_contents = TabContents::FromWebContents(web_contents()); |
| 287 if (!tab_contents) | 354 if (!tab_contents) |
| 288 return NULL; | 355 return NULL; |
| 289 return tab_contents->infobar_tab_helper(); | 356 return tab_contents->infobar_tab_helper(); |
| 290 } | 357 } |
| OLD | NEW |