Chromium Code Reviews| Index: chrome/browser/ui/views/hung_renderer_view_win.cc |
| =================================================================== |
| --- chrome/browser/ui/views/hung_renderer_view_win.cc (revision 147919) |
| +++ chrome/browser/ui/views/hung_renderer_view_win.cc (working copy) |
| @@ -4,17 +4,161 @@ |
| #include "chrome/browser/ui/views/hung_renderer_view_win.h" |
| +#include "base/win/metro.h" |
| +#include "chrome/browser/hang_monitor/hang_crash_dump_win.h" |
| +#include "chrome/browser/ui/views/hung_renderer_view.h" |
| +#include "content/public/browser/browser_thread.h" |
| +#include "content/public/browser/render_process_host.h" |
| +#include "grit/generated_resources.h" |
| +#include "ui/base/l10n/l10n_util.h" |
| + |
| +// Metro functions for displaying and dismissing a dialog box. |
| +typedef void (*MetroShowDialogBox)( |
| + const wchar_t* title, |
| + const wchar_t* content, |
| + const wchar_t* button1_label, |
| + const wchar_t* button2_label, |
| + base::win::MetroDialogButtonPressedHandler button1_handler, |
| + base::win::MetroDialogButtonPressedHandler button2_handler); |
| + |
| +typedef void (*MetroDismissDialogBox)(); |
| + |
| +using content::BrowserThread; |
| +using content::WebContents; |
| + |
| +HungRendererDialogMetro* HungRendererDialogMetro::g_instance_ = NULL; |
| + |
| +bool PlatformShowCustomHungRendererDialog(WebContents* contents) { |
| + if (!base::win::IsMetroProcess()) |
| + return false; |
| + |
| + HungRendererDialogMetro::Create()->Show(contents); |
| + return true; |
| +} |
| + |
| +bool PlatformHideCustomHungRendererDialog(WebContents* contents) { |
| + if (!base::win::IsMetroProcess()) |
| + return false; |
| + |
| + if (HungRendererDialogMetro::GetInstance()) |
| + HungRendererDialogMetro::GetInstance()->Hide(contents); |
| + return true; |
| +} |
| + |
| // static |
| -HungRendererDialogView* HungRendererDialogView::Create() { |
| - if (!g_instance_) |
| - g_instance_ = new HungRendererDialogViewWin(); |
| +void HungRendererDialogView::KillRendererProcess( |
| + base::ProcessHandle process_handle) { |
| + // Try to generate a crash report for the hung process. |
| + CrashDumpAndTerminateHungChildProcess(process_handle); |
| +} |
| + |
| +// static |
| +HungRendererDialogMetro* HungRendererDialogMetro::Create() { |
| + if (!GetInstance()) |
| + g_instance_ = new HungRendererDialogMetro; |
| return g_instance_; |
| } |
| -void HungRendererDialogViewWin::ShowForWebContents(WebContents* contents) { |
| - HungRendererDialogView::ShowForWebContents(contents); |
| +// static |
| +HungRendererDialogMetro* HungRendererDialogMetro::GetInstance() { |
| + return g_instance_; |
| } |
| -void HungRendererDialogViewWin::EndForWebContents(WebContents* contents) { |
| - HungRendererDialogView::EndForWebContents(contents); |
| +HungRendererDialogMetro::HungRendererDialogMetro() |
| + : contents_(NULL), |
| + metro_dialog_displayed_(false) { |
| } |
| + |
| +HungRendererDialogMetro::~HungRendererDialogMetro() { |
| +} |
| + |
| +void HungRendererDialogMetro::Show(WebContents* contents) { |
| + if (!metro_dialog_displayed_ && |
| + HungRendererDialogView::IsFrameActive(contents)) { |
| + HMODULE metro_dll = base::win::GetMetroModule(); |
| + DCHECK(metro_dll); |
| + if (metro_dll) { |
| + MetroShowDialogBox show_dialog_box = reinterpret_cast<MetroShowDialogBox> |
| + (::GetProcAddress(metro_dll, "ShowDialogBox")); |
| + DCHECK(show_dialog_box); |
| + if (show_dialog_box) { |
| + string16 dialog_box_title = |
| + l10n_util::GetStringUTF16(IDS_BROWSER_HANGMONITOR_RENDERER_TITLE); |
| + |
| + string16 kill_button_label = |
| + l10n_util::GetStringUTF16(IDS_BROWSER_HANGMONITOR_RENDERER_END); |
| + |
| + string16 wait_button_label = |
| + l10n_util::GetStringUTF16(IDS_BROWSER_HANGMONITOR_RENDERER_WAIT); |
| + |
| + contents_ = contents; |
| + metro_dialog_displayed_ = true; |
| + |
| + (*show_dialog_box)(dialog_box_title.c_str(), |
| + contents->GetTitle().c_str(), |
| + kill_button_label.c_str(), |
| + wait_button_label.c_str(), |
| + HungRendererDialogMetro::OnMetroKillProcess, |
| + HungRendererDialogMetro::OnMetroWait); |
| + } |
| + } |
| + } |
| +} |
| + |
| +void HungRendererDialogMetro::Hide(WebContents* contents) { |
| + HMODULE metro_dll = base::win::GetMetroModule(); |
| + DCHECK(metro_dll); |
| + if (metro_dll) { |
| + MetroDismissDialogBox dismiss_dialog_box = |
| + reinterpret_cast<MetroDismissDialogBox> |
| + (::GetProcAddress(metro_dll, "DismissDialogBox")); |
| + DCHECK(dismiss_dialog_box); |
| + if (dismiss_dialog_box) { |
| + (*dismiss_dialog_box)(); |
| + ResetMetroState(); |
| + } |
| + } |
| +} |
| + |
| +void HungRendererDialogMetro::ResetMetroState() { |
| + metro_dialog_displayed_ = false; |
| + contents_ = NULL; |
| + delete g_instance_; |
| + g_instance_ = NULL; |
|
sky
2012/07/24 23:40:33
move resetting g_instance_ to the destructor (safe
ananta
2012/07/24 23:45:15
Done.
|
| +} |
| + |
| +// static |
| +void HungRendererDialogMetro::OnMetroKillProcess() { |
| + // Metro chrome will invoke these handlers on the metro thread. Ensure that |
| + // we switch to the UI thread. |
| + if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| + BrowserThread::PostTask( |
| + BrowserThread::UI, FROM_HERE, |
| + base::Bind(HungRendererDialogMetro::OnMetroKillProcess)); |
| + return; |
| + } |
| + |
| + DCHECK(GetInstance()); |
|
sky
2012/07/24 23:40:33
I think you should just return here. I could see t
ananta
2012/07/24 23:45:15
Done.
|
| + DCHECK(GetInstance()->contents_); |
| + |
| + HungRendererDialogView::KillRendererProcess( |
| + GetInstance()->contents_->GetRenderProcessHost()->GetHandle()); |
| + |
| + // The metro dialog box is dismissed when the button handlers are invoked. |
| + GetInstance()->ResetMetroState(); |
| +} |
| + |
| +// static |
| +void HungRendererDialogMetro::OnMetroWait() { |
| + // Metro chrome will invoke these handlers on the metro thread. Ensure that |
| + // we switch to the UI thread. |
| + if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| + BrowserThread::PostTask( |
| + BrowserThread::UI, FROM_HERE, |
| + base::Bind(HungRendererDialogMetro::OnMetroWait)); |
| + return; |
| + } |
| + |
| + DCHECK(GetInstance()); |
|
sky
2012/07/24 23:40:33
Same comment here, just return if no instance.
ananta
2012/07/24 23:45:15
Done.
|
| + GetInstance()->ResetMetroState(); |
| +} |