Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / views / hung_renderer_view_win.cc
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 }