diff options
-rw-r--r-- | chrome/browser/hang_monitor/hung_plugin_action.cc | 76 | ||||
-rw-r--r-- | chrome/browser/hang_monitor/hung_plugin_action.h | 11 | ||||
-rw-r--r-- | webkit/plugins/npapi/webplugin_delegate_impl.h | 2 | ||||
-rw-r--r-- | webkit/plugins/npapi/webplugin_delegate_impl_win.cc | 65 |
4 files changed, 119 insertions, 35 deletions
diff --git a/chrome/browser/hang_monitor/hung_plugin_action.cc b/chrome/browser/hang_monitor/hung_plugin_action.cc index 57951c9..f8c5606 100644 --- a/chrome/browser/hang_monitor/hung_plugin_action.cc +++ b/chrome/browser/hang_monitor/hung_plugin_action.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,13 +6,56 @@ #include "chrome/browser/hang_monitor/hung_plugin_action.h" +#include "base/metrics/histogram.h" +#include "base/version.h" #include "chrome/browser/simple_message_box.h" #include "chrome/common/logging_chrome.h" #include "grit/generated_resources.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/win/hwnd_util.h" +#include "webkit/plugins/npapi/plugin_group.h" #include "webkit/plugins/npapi/webplugin_delegate_impl.h" +namespace { + +const wchar_t kGTalkPluginName[] = L"Google Talk Plugin"; +const int kGTalkPluginLogMinVersion = 26; // For version 2.6 and below. + +enum GTalkPluginLogVersion { + GTALK_PLUGIN_VERSION_MIN = 0, + GTALK_PLUGIN_VERSION_27, + GTALK_PLUGIN_VERSION_28, + GTALK_PLUGIN_VERSION_29, + GTALK_PLUGIN_VERSION_30, + GTALK_PLUGIN_VERSION_31, + GTALK_PLUGIN_VERSION_32, + GTALK_PLUGIN_VERSION_33, + GTALK_PLUGIN_VERSION_34, + GTALK_PLUGIN_VERSION_MAX +}; + +// Converts the version string of Google Talk Plugin to a version enum. The +// version format is "major(1 digit).minor(1 digit).sub(1 or 2 digits)", +// for example, "2.7.10" and "2.8.1". Converts the string to a number as +// 10 * major + minor - kGTalkPluginLogMinVersion. +GTalkPluginLogVersion GetGTalkPluginVersion(const string16& version) { + int gtalk_plugin_version = GTALK_PLUGIN_VERSION_MIN; + scoped_ptr<Version> plugin_version( + webkit::npapi::PluginGroup::CreateVersionFromString(version)); + if (plugin_version.get() && plugin_version->components().size() >= 2) { + gtalk_plugin_version = 10 * plugin_version->components()[0] + + plugin_version->components()[1] - kGTalkPluginLogMinVersion; + } + + if (gtalk_plugin_version < GTALK_PLUGIN_VERSION_MIN) + return GTALK_PLUGIN_VERSION_MIN; + if (gtalk_plugin_version > GTALK_PLUGIN_VERSION_MAX) + return GTALK_PLUGIN_VERSION_MAX; + return static_cast<GTalkPluginLogVersion>(gtalk_plugin_version); +} + +} // namespace + HungPluginAction::HungPluginAction() : current_hung_plugin_window_(NULL) { } @@ -38,17 +81,24 @@ bool HungPluginAction::OnHungWindowDetected(HWND hung_window, *action = HungWindowNotification::HUNG_WINDOW_IGNORE; if (top_level_window_process_id != hung_window_process_id) { + string16 plugin_name; + string16 plugin_version; + GetPluginNameAndVersion(hung_window, + top_level_window_process_id, + &plugin_name, + &plugin_version); + if (plugin_name.empty()) { + plugin_name = l10n_util::GetStringUTF16(IDS_UNKNOWN_PLUGIN_NAME); + } else if (kGTalkPluginName == plugin_name) { + UMA_HISTOGRAM_ENUMERATION("GTalkPlugin.Hung", + GetGTalkPluginVersion(plugin_version), + GTALK_PLUGIN_VERSION_MAX + 1); + } + if (logging::DialogsAreSuppressed()) { NOTREACHED() << "Terminated a hung plugin process."; *action = HungWindowNotification::HUNG_WINDOW_TERMINATE_PROCESS; } else { - string16 plugin_name; - GetPluginName(hung_window, - top_level_window_process_id, - &plugin_name); - if (plugin_name.empty()) { - plugin_name = l10n_util::GetStringUTF16(IDS_UNKNOWN_PLUGIN_NAME); - } string16 msg = l10n_util::GetStringFUTF16(IDS_BROWSER_HANGMONITOR, plugin_name); string16 title = l10n_util::GetStringUTF16(IDS_BROWSER_HANGMONITOR_TITLE); @@ -107,10 +157,12 @@ void HungPluginAction::OnWindowResponsive(HWND window) { } } -bool HungPluginAction::GetPluginName(HWND plugin_window, - DWORD browser_process_id, - std::wstring* plugin_name) { +bool HungPluginAction::GetPluginNameAndVersion(HWND plugin_window, + DWORD browser_process_id, + string16* plugin_name, + string16* plugin_version) { DCHECK(plugin_name); + DCHECK(plugin_version); HWND window_to_check = plugin_window; while (NULL != window_to_check) { DWORD process_id = 0; @@ -122,6 +174,8 @@ bool HungPluginAction::GetPluginName(HWND plugin_window, } if (webkit::npapi::WebPluginDelegateImpl::GetPluginNameFromWindow( window_to_check, plugin_name)) { + webkit::npapi::WebPluginDelegateImpl::GetPluginVersionFromWindow( + window_to_check, plugin_version); return true; } window_to_check = GetParent(window_to_check); diff --git a/chrome/browser/hang_monitor/hung_plugin_action.h b/chrome/browser/hang_monitor/hung_plugin_action.h index 4958def..a4b89b9 100644 --- a/chrome/browser/hang_monitor/hung_plugin_action.h +++ b/chrome/browser/hang_monitor/hung_plugin_action.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,7 +6,9 @@ #define CHROME_BROWSER_HANG_MONITOR_HUNG_PLUGIN_ACTION_H__ #pragma once +#include "base/string16.h" #include "chrome/browser/hang_monitor/hung_window_detector.h" + // This class provides an implementation the // HungWindowDetector::HungWindowNotification callback interface. // It checks to see if the hung window belongs to a process different @@ -36,9 +38,10 @@ class HungPluginAction : public HungWindowDetector::HungWindowNotification { static BOOL CALLBACK DismissMessageBox(HWND window, LPARAM ignore); protected: - bool GetPluginName(HWND plugin_window, - DWORD browser_process_id, - std::wstring *plugin_name); + bool GetPluginNameAndVersion(HWND plugin_window, + DWORD browser_process_id, + string16* plugin_name, + string16* plugin_version); // The currently hung plugin window that we are prompting the user about HWND current_hung_plugin_window_; }; diff --git a/webkit/plugins/npapi/webplugin_delegate_impl.h b/webkit/plugins/npapi/webplugin_delegate_impl.h index 8bdf50e..2e5e333 100644 --- a/webkit/plugins/npapi/webplugin_delegate_impl.h +++ b/webkit/plugins/npapi/webplugin_delegate_impl.h @@ -95,6 +95,8 @@ class WEBKIT_PLUGINS_EXPORT WebPluginDelegateImpl : public WebPluginDelegate { static bool IsPluginDelegateWindow(gfx::NativeWindow window); static bool GetPluginNameFromWindow(gfx::NativeWindow window, string16* plugin_name); + static bool GetPluginVersionFromWindow(gfx::NativeWindow window, + string16* plugin_version); // Returns true if the window handle passed in is that of the dummy // activation window for windowless plugins. diff --git a/webkit/plugins/npapi/webplugin_delegate_impl_win.cc b/webkit/plugins/npapi/webplugin_delegate_impl_win.cc index f308202..2b1229a 100644 --- a/webkit/plugins/npapi/webplugin_delegate_impl_win.cc +++ b/webkit/plugins/npapi/webplugin_delegate_impl_win.cc @@ -48,6 +48,7 @@ namespace { const wchar_t kWebPluginDelegateProperty[] = L"WebPluginDelegateProperty"; const wchar_t kPluginNameAtomProperty[] = L"PluginNameAtom"; +const wchar_t kPluginVersionAtomProperty[] = L"PluginVersionAtom"; const wchar_t kDummyActivationWindowName[] = L"DummyWindowForActivation"; const wchar_t kPluginFlashThrottle[] = L"FlashThrottle"; @@ -263,6 +264,22 @@ int GetPluginMajorVersion(const WebPluginInfo& plugin_info) { return major_version; } +bool GetPluginPropertyFromWindow( + HWND window, const wchar_t* plugin_atom_property, + string16* plugin_property) { + ATOM plugin_atom = reinterpret_cast<ATOM>( + GetPropW(window, plugin_atom_property)); + if (plugin_atom != 0) { + WCHAR plugin_property_local[MAX_PATH] = {0}; + GlobalGetAtomNameW(plugin_atom, + plugin_property_local, + ARRAYSIZE(plugin_property_local)); + *plugin_property = plugin_property_local; + return true; + } + return false; +} + } // namespace bool WebPluginDelegateImpl::IsPluginDelegateWindow(HWND window) { @@ -276,23 +293,17 @@ bool WebPluginDelegateImpl::IsPluginDelegateWindow(HWND window) { // static bool WebPluginDelegateImpl::GetPluginNameFromWindow( HWND window, string16* plugin_name) { - if (NULL == plugin_name) { - return false; - } - if (!IsPluginDelegateWindow(window)) { - return false; - } - ATOM plugin_name_atom = reinterpret_cast<ATOM>( - GetPropW(window, kPluginNameAtomProperty)); - if (plugin_name_atom != 0) { - WCHAR plugin_name_local[MAX_PATH] = {0}; - GlobalGetAtomNameW(plugin_name_atom, - plugin_name_local, - ARRAYSIZE(plugin_name_local)); - *plugin_name = plugin_name_local; - return true; - } - return false; + return IsPluginDelegateWindow(window) && + GetPluginPropertyFromWindow( + window, kPluginNameAtomProperty, plugin_name); +} + +// static +bool WebPluginDelegateImpl::GetPluginVersionFromWindow( + HWND window, string16* plugin_version) { + return IsPluginDelegateWindow(window) && + GetPluginPropertyFromWindow( + window, kPluginVersionAtomProperty, plugin_version); } bool WebPluginDelegateImpl::IsDummyActivationWindow(HWND window) { @@ -695,9 +706,9 @@ bool WebPluginDelegateImpl::WindowedCreatePlugin() { BOOL result = SetProp(windowed_handle_, kWebPluginDelegateProperty, this); DCHECK(result == TRUE) << "SetProp failed, last error = " << GetLastError(); - // Get the name of the plugin, create an atom and set that in a window - // property. Use an atom so that other processes can access the name of - // the plugin that this window is hosting + // Get the name and version of the plugin, create atoms and set them in a + // window property. Use atoms so that other processes can access the name and + // version of the plugin that this window is hosting. if (instance_ != NULL) { PluginLib* plugin_lib = instance()->plugin_lib(); if (plugin_lib != NULL) { @@ -711,6 +722,16 @@ bool WebPluginDelegateImpl::WindowedCreatePlugin() { DCHECK(result == TRUE) << "SetProp failed, last error = " << GetLastError(); } + string16 plugin_version = plugin_lib->plugin_info().version; + if (!plugin_version.empty()) { + ATOM plugin_version_atom = GlobalAddAtomW(plugin_version.c_str()); + DCHECK(0 != plugin_version_atom); + result = SetProp(windowed_handle_, + kPluginVersionAtomProperty, + reinterpret_cast<HANDLE>(plugin_version_atom)); + DCHECK(result == TRUE) << "SetProp failed, last error = " << + GetLastError(); + } } } @@ -1207,6 +1228,10 @@ LRESULT CALLBACK WebPluginDelegateImpl::NativeWndProc( RemoveProp(hwnd, kPluginNameAtomProperty)); if (plugin_name_atom != 0) GlobalDeleteAtom(plugin_name_atom); + ATOM plugin_version_atom = reinterpret_cast<ATOM>( + RemoveProp(hwnd, kPluginVersionAtomProperty)); + if (plugin_version_atom != 0) + GlobalDeleteAtom(plugin_version_atom); ClearThrottleQueueForWindow(hwnd); } } |