OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 <windows.h> | 5 #include <windows.h> |
6 | 6 |
7 #include "chrome/browser/hang_monitor/hung_plugin_action.h" | 7 #include "chrome/browser/hang_monitor/hung_plugin_action.h" |
8 | 8 |
9 #include "base/metrics/histogram.h" | |
10 #include "base/version.h" | |
9 #include "chrome/browser/simple_message_box.h" | 11 #include "chrome/browser/simple_message_box.h" |
10 #include "chrome/common/logging_chrome.h" | 12 #include "chrome/common/logging_chrome.h" |
11 #include "grit/generated_resources.h" | 13 #include "grit/generated_resources.h" |
12 #include "ui/base/l10n/l10n_util.h" | 14 #include "ui/base/l10n/l10n_util.h" |
13 #include "ui/base/win/hwnd_util.h" | 15 #include "ui/base/win/hwnd_util.h" |
16 #include "webkit/plugins/npapi/plugin_group.h" | |
14 #include "webkit/plugins/npapi/webplugin_delegate_impl.h" | 17 #include "webkit/plugins/npapi/webplugin_delegate_impl.h" |
15 | 18 |
19 namespace { | |
20 | |
21 const wchar_t kGTalkPluginName[] = L"Google Talk Plugin"; | |
22 | |
23 enum GTalkPluginVersion { | |
24 GTALK_PLUGIN_VERSION_MIN = 26, | |
25 GTALK_PLUGIN_VERSION_27 = 27, | |
26 GTALK_PLUGIN_VERSION_28 = 28, | |
27 GTALK_PLUGIN_VERSION_29 = 29, | |
28 GTALK_PLUGIN_VERSION_30 = 30, | |
29 GTALK_PLUGIN_VERSION_31 = 31, | |
30 GTALK_PLUGIN_VERSION_32 = 32, | |
31 GTALK_PLUGIN_VERSION_33 = 33, | |
32 GTALK_PLUGIN_VERSION_34 = 34, | |
33 GTALK_PLUGIN_VERSION_MAX = 35 | |
34 }; | |
35 | |
36 // Converts the version string of Google Talk Plugin to a version enum. The | |
37 // version format is "major(1 digit).minor(1 digit).sub(1 or 2 digits)", | |
38 // for example, "2.7.10" and "2.8.1". Converts the string to a number as | |
39 // 10 * major + minor. | |
40 GTalkPluginVersion GetGTalkPluginVersion(const string16& version) { | |
41 int gtalk_plugin_version = GTALK_PLUGIN_VERSION_MIN; | |
42 scoped_ptr<Version> plugin_version( | |
43 webkit::npapi::PluginGroup::CreateVersionFromString(version)); | |
44 if (plugin_version.get() && plugin_version->components().size() >= 2) { | |
45 gtalk_plugin_version = 10 * plugin_version->components()[0] + | |
46 plugin_version->components()[1]; | |
47 } | |
48 | |
49 if (gtalk_plugin_version < GTALK_PLUGIN_VERSION_MIN) { | |
50 return GTALK_PLUGIN_VERSION_MIN; | |
51 } else if (gtalk_plugin_version > GTALK_PLUGIN_VERSION_MAX) { | |
jar (doing other things)
2012/04/11 22:26:59
nit: Since you return, you don't need else clauses
whyuan
2012/04/12 21:02:19
Done.
| |
52 return GTALK_PLUGIN_VERSION_MAX; | |
53 } else { | |
54 return static_cast<GTalkPluginVersion>(gtalk_plugin_version); | |
55 } | |
56 } | |
57 | |
58 } // namespace | |
59 | |
16 HungPluginAction::HungPluginAction() : current_hung_plugin_window_(NULL) { | 60 HungPluginAction::HungPluginAction() : current_hung_plugin_window_(NULL) { |
17 } | 61 } |
18 | 62 |
19 HungPluginAction::~HungPluginAction() { | 63 HungPluginAction::~HungPluginAction() { |
20 } | 64 } |
21 | 65 |
22 bool HungPluginAction::OnHungWindowDetected(HWND hung_window, | 66 bool HungPluginAction::OnHungWindowDetected(HWND hung_window, |
23 HWND top_level_window, | 67 HWND top_level_window, |
24 ActionOnHungWindow* action) { | 68 ActionOnHungWindow* action) { |
25 if (NULL == action) { | 69 if (NULL == action) { |
26 return false; | 70 return false; |
27 } | 71 } |
28 if (!IsWindow(hung_window)) { | 72 if (!IsWindow(hung_window)) { |
29 return false; | 73 return false; |
30 } | 74 } |
31 | 75 |
32 bool continue_hang_detection = true; | 76 bool continue_hang_detection = true; |
33 | 77 |
34 DWORD hung_window_process_id = 0; | 78 DWORD hung_window_process_id = 0; |
35 DWORD top_level_window_process_id = 0; | 79 DWORD top_level_window_process_id = 0; |
36 GetWindowThreadProcessId(hung_window, &hung_window_process_id); | 80 GetWindowThreadProcessId(hung_window, &hung_window_process_id); |
37 GetWindowThreadProcessId(top_level_window, &top_level_window_process_id); | 81 GetWindowThreadProcessId(top_level_window, &top_level_window_process_id); |
38 | 82 |
39 *action = HungWindowNotification::HUNG_WINDOW_IGNORE; | 83 *action = HungWindowNotification::HUNG_WINDOW_IGNORE; |
40 if (top_level_window_process_id != hung_window_process_id) { | 84 if (top_level_window_process_id != hung_window_process_id) { |
85 string16 plugin_name; | |
86 string16 plugin_version; | |
87 GetPluginNameAndVersion(hung_window, | |
88 top_level_window_process_id, | |
89 &plugin_name, | |
90 &plugin_version); | |
91 if (plugin_name.empty()) { | |
92 plugin_name = l10n_util::GetStringUTF16(IDS_UNKNOWN_PLUGIN_NAME); | |
93 } else if (kGTalkPluginName == plugin_name) { | |
94 UMA_HISTOGRAM_ENUMERATION("GTalkPlugin.Hung", | |
95 GetGTalkPluginVersion(plugin_version), | |
96 GTALK_PLUGIN_VERSION_MAX + 1); | |
jar (doing other things)
2012/04/11 22:26:59
This will create a histogram with the full 37 buck
whyuan
2012/04/12 21:02:19
Reduced to 11
On 2012/04/11 22:26:59, jar wrote:
| |
97 } | |
98 | |
41 if (logging::DialogsAreSuppressed()) { | 99 if (logging::DialogsAreSuppressed()) { |
42 NOTREACHED() << "Terminated a hung plugin process."; | 100 NOTREACHED() << "Terminated a hung plugin process."; |
43 *action = HungWindowNotification::HUNG_WINDOW_TERMINATE_PROCESS; | 101 *action = HungWindowNotification::HUNG_WINDOW_TERMINATE_PROCESS; |
44 } else { | 102 } else { |
45 string16 plugin_name; | |
46 GetPluginName(hung_window, | |
47 top_level_window_process_id, | |
48 &plugin_name); | |
49 if (plugin_name.empty()) { | |
50 plugin_name = l10n_util::GetStringUTF16(IDS_UNKNOWN_PLUGIN_NAME); | |
51 } | |
52 string16 msg = l10n_util::GetStringFUTF16(IDS_BROWSER_HANGMONITOR, | 103 string16 msg = l10n_util::GetStringFUTF16(IDS_BROWSER_HANGMONITOR, |
53 plugin_name); | 104 plugin_name); |
54 string16 title = l10n_util::GetStringUTF16(IDS_BROWSER_HANGMONITOR_TITLE); | 105 string16 title = l10n_util::GetStringUTF16(IDS_BROWSER_HANGMONITOR_TITLE); |
55 // Before displaying the message box, invoke SendMessageCallback on the | 106 // Before displaying the message box, invoke SendMessageCallback on the |
56 // hung window. If the callback ever hits, the window is not hung anymore | 107 // hung window. If the callback ever hits, the window is not hung anymore |
57 // and we can dismiss the message box. | 108 // and we can dismiss the message box. |
58 SendMessageCallback(hung_window, | 109 SendMessageCallback(hung_window, |
59 WM_NULL, | 110 WM_NULL, |
60 0, | 111 0, |
61 0, | 112 0, |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
100 // The message timeout for this window should fallback to the default | 151 // The message timeout for this window should fallback to the default |
101 // timeout as this window is now responsive. | 152 // timeout as this window is now responsive. |
102 RemoveProp(window, HungWindowDetector::kHungChildWindowTimeout); | 153 RemoveProp(window, HungWindowDetector::kHungChildWindowTimeout); |
103 // The monitored plugin recovered. Let's dismiss the message box. | 154 // The monitored plugin recovered. Let's dismiss the message box. |
104 EnumThreadWindows(GetCurrentThreadId(), | 155 EnumThreadWindows(GetCurrentThreadId(), |
105 reinterpret_cast<WNDENUMPROC>(DismissMessageBox), | 156 reinterpret_cast<WNDENUMPROC>(DismissMessageBox), |
106 NULL); | 157 NULL); |
107 } | 158 } |
108 } | 159 } |
109 | 160 |
110 bool HungPluginAction::GetPluginName(HWND plugin_window, | 161 bool HungPluginAction::GetPluginNameAndVersion(HWND plugin_window, |
111 DWORD browser_process_id, | 162 DWORD browser_process_id, |
112 std::wstring* plugin_name) { | 163 std::wstring* plugin_name, |
164 std::wstring* plugin_version) { | |
113 DCHECK(plugin_name); | 165 DCHECK(plugin_name); |
166 DCHECK(plugin_version); | |
114 HWND window_to_check = plugin_window; | 167 HWND window_to_check = plugin_window; |
115 while (NULL != window_to_check) { | 168 while (NULL != window_to_check) { |
116 DWORD process_id = 0; | 169 DWORD process_id = 0; |
117 GetWindowThreadProcessId(window_to_check, &process_id); | 170 GetWindowThreadProcessId(window_to_check, &process_id); |
118 if (process_id == browser_process_id) { | 171 if (process_id == browser_process_id) { |
119 // If we have reached a window the that belongs to the browser process | 172 // If we have reached a window the that belongs to the browser process |
120 // we have gone too far. | 173 // we have gone too far. |
121 return false; | 174 return false; |
122 } | 175 } |
123 if (webkit::npapi::WebPluginDelegateImpl::GetPluginNameFromWindow( | 176 if (webkit::npapi::WebPluginDelegateImpl::GetPluginNameFromWindow( |
124 window_to_check, plugin_name)) { | 177 window_to_check, plugin_name)) { |
178 webkit::npapi::WebPluginDelegateImpl::GetPluginVersionFromWindow( | |
179 window_to_check, plugin_version); | |
125 return true; | 180 return true; |
126 } | 181 } |
127 window_to_check = GetParent(window_to_check); | 182 window_to_check = GetParent(window_to_check); |
128 } | 183 } |
129 return false; | 184 return false; |
130 } | 185 } |
131 | 186 |
132 // static | 187 // static |
133 BOOL CALLBACK HungPluginAction::DismissMessageBox(HWND window, LPARAM ignore) { | 188 BOOL CALLBACK HungPluginAction::DismissMessageBox(HWND window, LPARAM ignore) { |
134 string16 class_name = ui::GetClassName(window); | 189 string16 class_name = ui::GetClassName(window); |
(...skipping 10 matching lines...) Expand all Loading... | |
145 void CALLBACK HungPluginAction::HungWindowResponseCallback(HWND target_window, | 200 void CALLBACK HungPluginAction::HungWindowResponseCallback(HWND target_window, |
146 UINT message, | 201 UINT message, |
147 ULONG_PTR data, | 202 ULONG_PTR data, |
148 LRESULT result) { | 203 LRESULT result) { |
149 HungPluginAction* instance = reinterpret_cast<HungPluginAction*>(data); | 204 HungPluginAction* instance = reinterpret_cast<HungPluginAction*>(data); |
150 DCHECK(NULL != instance); | 205 DCHECK(NULL != instance); |
151 if (NULL != instance) { | 206 if (NULL != instance) { |
152 instance->OnWindowResponsive(target_window); | 207 instance->OnWindowResponsive(target_window); |
153 } | 208 } |
154 } | 209 } |
OLD | NEW |