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 |