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/views/hung_renderer_view_win.h" | 5 #include "chrome/browser/ui/views/hung_renderer_view_win.h" |
6 | 6 |
| 7 #include "base/win/metro.h" |
| 8 #include "chrome/browser/hang_monitor/hang_crash_dump_win.h" |
| 9 #include "chrome/browser/ui/views/hung_renderer_view.h" |
| 10 #include "content/public/browser/browser_thread.h" |
| 11 #include "content/public/browser/render_process_host.h" |
| 12 #include "grit/generated_resources.h" |
| 13 #include "ui/base/l10n/l10n_util.h" |
| 14 |
| 15 // Metro functions for displaying and dismissing a dialog box. |
| 16 typedef void (*MetroShowDialogBox)( |
| 17 const wchar_t* title, |
| 18 const wchar_t* content, |
| 19 const wchar_t* button1_label, |
| 20 const wchar_t* button2_label, |
| 21 base::win::MetroDialogButtonPressedHandler button1_handler, |
| 22 base::win::MetroDialogButtonPressedHandler button2_handler); |
| 23 |
| 24 typedef void (*MetroDismissDialogBox)(); |
| 25 |
| 26 using content::BrowserThread; |
| 27 using content::WebContents; |
| 28 |
| 29 HungRendererDialogMetro* HungRendererDialogMetro::g_instance_ = NULL; |
| 30 |
| 31 bool PlatformShowCustomHungRendererDialog(WebContents* contents) { |
| 32 if (!base::win::IsMetroProcess()) |
| 33 return false; |
| 34 |
| 35 HungRendererDialogMetro::Create()->Show(contents); |
| 36 return true; |
| 37 } |
| 38 |
| 39 bool PlatformHideCustomHungRendererDialog(WebContents* contents) { |
| 40 if (!base::win::IsMetroProcess()) |
| 41 return false; |
| 42 |
| 43 if (HungRendererDialogMetro::GetInstance()) |
| 44 HungRendererDialogMetro::GetInstance()->Hide(contents); |
| 45 return true; |
| 46 } |
| 47 |
7 // static | 48 // static |
8 HungRendererDialogView* HungRendererDialogView::Create() { | 49 void HungRendererDialogView::KillRendererProcess( |
9 if (!g_instance_) | 50 base::ProcessHandle process_handle) { |
10 g_instance_ = new HungRendererDialogViewWin(); | 51 // Try to generate a crash report for the hung process. |
| 52 CrashDumpAndTerminateHungChildProcess(process_handle); |
| 53 } |
| 54 |
| 55 // static |
| 56 HungRendererDialogMetro* HungRendererDialogMetro::Create() { |
| 57 if (!GetInstance()) |
| 58 g_instance_ = new HungRendererDialogMetro; |
11 return g_instance_; | 59 return g_instance_; |
12 } | 60 } |
13 | 61 |
14 void HungRendererDialogViewWin::ShowForWebContents(WebContents* contents) { | 62 // static |
15 HungRendererDialogView::ShowForWebContents(contents); | 63 HungRendererDialogMetro* HungRendererDialogMetro::GetInstance() { |
| 64 return g_instance_; |
16 } | 65 } |
17 | 66 |
18 void HungRendererDialogViewWin::EndForWebContents(WebContents* contents) { | 67 HungRendererDialogMetro::HungRendererDialogMetro() |
19 HungRendererDialogView::EndForWebContents(contents); | 68 : contents_(NULL), |
| 69 metro_dialog_displayed_(false) { |
20 } | 70 } |
| 71 |
| 72 HungRendererDialogMetro::~HungRendererDialogMetro() { |
| 73 g_instance_ = NULL; |
| 74 } |
| 75 |
| 76 void HungRendererDialogMetro::Show(WebContents* contents) { |
| 77 if (!metro_dialog_displayed_ && |
| 78 HungRendererDialogView::IsFrameActive(contents)) { |
| 79 HMODULE metro_dll = base::win::GetMetroModule(); |
| 80 DCHECK(metro_dll); |
| 81 if (metro_dll) { |
| 82 MetroShowDialogBox show_dialog_box = reinterpret_cast<MetroShowDialogBox> |
| 83 (::GetProcAddress(metro_dll, "ShowDialogBox")); |
| 84 DCHECK(show_dialog_box); |
| 85 if (show_dialog_box) { |
| 86 string16 dialog_box_title = |
| 87 l10n_util::GetStringUTF16(IDS_BROWSER_HANGMONITOR_RENDERER_TITLE); |
| 88 |
| 89 string16 kill_button_label = |
| 90 l10n_util::GetStringUTF16(IDS_BROWSER_HANGMONITOR_RENDERER_END); |
| 91 |
| 92 string16 wait_button_label = |
| 93 l10n_util::GetStringUTF16(IDS_BROWSER_HANGMONITOR_RENDERER_WAIT); |
| 94 |
| 95 contents_ = contents; |
| 96 metro_dialog_displayed_ = true; |
| 97 |
| 98 (*show_dialog_box)(dialog_box_title.c_str(), |
| 99 contents->GetTitle().c_str(), |
| 100 kill_button_label.c_str(), |
| 101 wait_button_label.c_str(), |
| 102 HungRendererDialogMetro::OnMetroKillProcess, |
| 103 HungRendererDialogMetro::OnMetroWait); |
| 104 } |
| 105 } |
| 106 } |
| 107 } |
| 108 |
| 109 void HungRendererDialogMetro::Hide(WebContents* contents) { |
| 110 HMODULE metro_dll = base::win::GetMetroModule(); |
| 111 DCHECK(metro_dll); |
| 112 if (metro_dll) { |
| 113 MetroDismissDialogBox dismiss_dialog_box = |
| 114 reinterpret_cast<MetroDismissDialogBox> |
| 115 (::GetProcAddress(metro_dll, "DismissDialogBox")); |
| 116 DCHECK(dismiss_dialog_box); |
| 117 if (dismiss_dialog_box) { |
| 118 (*dismiss_dialog_box)(); |
| 119 ResetMetroState(); |
| 120 } |
| 121 } |
| 122 } |
| 123 |
| 124 void HungRendererDialogMetro::ResetMetroState() { |
| 125 metro_dialog_displayed_ = false; |
| 126 contents_ = NULL; |
| 127 delete g_instance_; |
| 128 } |
| 129 |
| 130 // static |
| 131 void HungRendererDialogMetro::OnMetroKillProcess() { |
| 132 // Metro chrome will invoke these handlers on the metro thread. Ensure that |
| 133 // we switch to the UI thread. |
| 134 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| 135 BrowserThread::PostTask( |
| 136 BrowserThread::UI, FROM_HERE, |
| 137 base::Bind(HungRendererDialogMetro::OnMetroKillProcess)); |
| 138 return; |
| 139 } |
| 140 |
| 141 // Its possible that we got deleted in the meantime. |
| 142 if (!GetInstance()) |
| 143 return; |
| 144 |
| 145 DCHECK(GetInstance()->contents_); |
| 146 |
| 147 HungRendererDialogView::KillRendererProcess( |
| 148 GetInstance()->contents_->GetRenderProcessHost()->GetHandle()); |
| 149 |
| 150 // The metro dialog box is dismissed when the button handlers are invoked. |
| 151 GetInstance()->ResetMetroState(); |
| 152 } |
| 153 |
| 154 // static |
| 155 void HungRendererDialogMetro::OnMetroWait() { |
| 156 // Metro chrome will invoke these handlers on the metro thread. Ensure that |
| 157 // we switch to the UI thread. |
| 158 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| 159 BrowserThread::PostTask( |
| 160 BrowserThread::UI, FROM_HERE, |
| 161 base::Bind(HungRendererDialogMetro::OnMetroWait)); |
| 162 return; |
| 163 } |
| 164 |
| 165 // Its possible that we got deleted in the meantime. |
| 166 if (!GetInstance()) |
| 167 return; |
| 168 |
| 169 GetInstance()->ResetMetroState(); |
| 170 } |
OLD | NEW |