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