Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(132)

Side by Side Diff: chrome/browser/hang_monitor/hung_plugin_action.cc

Issue 9958104: Log when a browser plugin hangs (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 const int kMaxGTalkPluginVersion = 10000;
23
24 // Converts the version string of Google Talk Plugin to a number. The
25 // version format is "major(1 digit).minor(1 digit).sub(1 or 2 digits)",
26 // for example, "2.7.10" and "2.8.1". Converts the string to a number as
27 // 1000 * major + 100 * minor + sub.
28 int GetGTalkPluginVersion(const string16& version) {
29 int gtalk_plugin_version = 0;
30 scoped_ptr<Version> plugin_version(
31 webkit::npapi::PluginGroup::CreateVersionFromString(version));
32 if (plugin_version.get() && plugin_version->components().size() >= 3) {
33 gtalk_plugin_version = plugin_version->components()[0] * 1000 +
34 plugin_version->components()[1] * 100 +
35 plugin_version->components()[2];
36 if (gtalk_plugin_version > kMaxGTalkPluginVersion) {
37 gtalk_plugin_version = kMaxGTalkPluginVersion;
38 }
39 }
40 return gtalk_plugin_version;
41 }
42
43 } // namespace
44
16 HungPluginAction::HungPluginAction() : current_hung_plugin_window_(NULL) { 45 HungPluginAction::HungPluginAction() : current_hung_plugin_window_(NULL) {
17 } 46 }
18 47
19 HungPluginAction::~HungPluginAction() { 48 HungPluginAction::~HungPluginAction() {
20 } 49 }
21 50
22 bool HungPluginAction::OnHungWindowDetected(HWND hung_window, 51 bool HungPluginAction::OnHungWindowDetected(HWND hung_window,
23 HWND top_level_window, 52 HWND top_level_window,
24 ActionOnHungWindow* action) { 53 ActionOnHungWindow* action) {
25 if (NULL == action) { 54 if (NULL == action) {
26 return false; 55 return false;
27 } 56 }
28 if (!IsWindow(hung_window)) { 57 if (!IsWindow(hung_window)) {
29 return false; 58 return false;
30 } 59 }
31 60
32 bool continue_hang_detection = true; 61 bool continue_hang_detection = true;
33 62
34 DWORD hung_window_process_id = 0; 63 DWORD hung_window_process_id = 0;
35 DWORD top_level_window_process_id = 0; 64 DWORD top_level_window_process_id = 0;
36 GetWindowThreadProcessId(hung_window, &hung_window_process_id); 65 GetWindowThreadProcessId(hung_window, &hung_window_process_id);
37 GetWindowThreadProcessId(top_level_window, &top_level_window_process_id); 66 GetWindowThreadProcessId(top_level_window, &top_level_window_process_id);
38 67
68 bool is_gtalk_plugin = false;
69 int gtalk_plugin_version = 0;
39 *action = HungWindowNotification::HUNG_WINDOW_IGNORE; 70 *action = HungWindowNotification::HUNG_WINDOW_IGNORE;
40 if (top_level_window_process_id != hung_window_process_id) { 71 if (top_level_window_process_id != hung_window_process_id) {
72 string16 plugin_name;
73 string16 plugin_version;
74 GetPluginNameAndVersion(hung_window,
75 top_level_window_process_id,
76 &plugin_name,
77 &plugin_version);
78 if (plugin_name.empty()) {
79 plugin_name = l10n_util::GetStringUTF16(IDS_UNKNOWN_PLUGIN_NAME);
80 }
81
82 is_gtalk_plugin = (kGTalkPluginName == plugin_name);
83 if (is_gtalk_plugin) {
84 gtalk_plugin_version = GetGTalkPluginVersion(plugin_version);
85 }
86
41 if (logging::DialogsAreSuppressed()) { 87 if (logging::DialogsAreSuppressed()) {
42 NOTREACHED() << "Terminated a hung plugin process."; 88 NOTREACHED() << "Terminated a hung plugin process.";
43 *action = HungWindowNotification::HUNG_WINDOW_TERMINATE_PROCESS; 89 *action = HungWindowNotification::HUNG_WINDOW_TERMINATE_PROCESS;
44 } else { 90 } 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, 91 string16 msg = l10n_util::GetStringFUTF16(IDS_BROWSER_HANGMONITOR,
53 plugin_name); 92 plugin_name);
54 string16 title = l10n_util::GetStringUTF16(IDS_BROWSER_HANGMONITOR_TITLE); 93 string16 title = l10n_util::GetStringUTF16(IDS_BROWSER_HANGMONITOR_TITLE);
55 // Before displaying the message box, invoke SendMessageCallback on the 94 // Before displaying the message box, invoke SendMessageCallback on the
56 // hung window. If the callback ever hits, the window is not hung anymore 95 // hung window. If the callback ever hits, the window is not hung anymore
57 // and we can dismiss the message box. 96 // and we can dismiss the message box.
58 SendMessageCallback(hung_window, 97 SendMessageCallback(hung_window,
59 WM_NULL, 98 WM_NULL,
60 0, 99 0,
61 0, 100 0,
(...skipping 22 matching lines...) Expand all
84 #pragma warning(default:4312) 123 #pragma warning(default:4312)
85 } 124 }
86 } 125 }
87 current_hung_plugin_window_ = NULL; 126 current_hung_plugin_window_ = NULL;
88 } 127 }
89 } 128 }
90 if (HungWindowNotification::HUNG_WINDOW_TERMINATE_PROCESS == *action) { 129 if (HungWindowNotification::HUNG_WINDOW_TERMINATE_PROCESS == *action) {
91 // Enable the top-level window just in case the plugin had been 130 // Enable the top-level window just in case the plugin had been
92 // displaying a modal box that had disabled the top-level window 131 // displaying a modal box that had disabled the top-level window
93 EnableWindow(top_level_window, TRUE); 132 EnableWindow(top_level_window, TRUE);
133
134 UMA_HISTOGRAM_COUNTS("Plugin.Hung_Terminate_Process", 1);
135 if (is_gtalk_plugin) {
136 UMA_HISTOGRAM_ENUMERATION("GTalkPlugin.Hung_Terminate_Process",
137 gtalk_plugin_version, kMaxGTalkPluginVersion + 1);
138 }
139 } else {
140 UMA_HISTOGRAM_COUNTS("Plugin.Hung_Ignore", 1);
141 if (is_gtalk_plugin) {
142 UMA_HISTOGRAM_ENUMERATION("GTalkPlugin.Hung_Ignore",
143 gtalk_plugin_version, kMaxGTalkPluginVersion + 1);
144 }
94 } 145 }
95 return continue_hang_detection; 146 return continue_hang_detection;
96 } 147 }
97 148
98 void HungPluginAction::OnWindowResponsive(HWND window) { 149 void HungPluginAction::OnWindowResponsive(HWND window) {
99 if (window == current_hung_plugin_window_) { 150 if (window == current_hung_plugin_window_) {
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698