plugin_metrics_provider.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// found in the LICENSE file. 4cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/metrics/plugin_metrics_provider.h" 6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <string> 8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/prefs/pref_registry_simple.h" 10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/prefs/pref_service.h" 11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/prefs/scoped_user_pref_update.h" 12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/stl_util.h" 13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/browser_process.h" 15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/plugins/plugin_prefs.h" 16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/profiles/profile_manager.h" 17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/common/pref_names.h" 18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/metrics/proto/system_profile.pb.h" 19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/public/browser/child_process_data.h" 20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/public/browser/plugin_service.h" 21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/public/common/process_type.h" 22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/public/common/webplugininfo.h" 23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace { 25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Returns the plugin preferences corresponding for this user, if available. 27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// If multiple user profiles are loaded, returns the preferences corresponding 28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// to an arbitrary one of the profiles. 29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)PluginPrefs* GetPluginPrefs() { 30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ProfileManager* profile_manager = g_browser_process->profile_manager(); 31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!profile_manager) { 33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // The profile manager can be NULL when testing. 34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return NULL; 35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::vector<Profile*> profiles = profile_manager->GetLoadedProfiles(); 38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (profiles.empty()) 39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return NULL; 40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return PluginPrefs::GetForProfile(profiles.front()).get(); 42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Fills |plugin| with the info contained in |plugin_info| and |plugin_prefs|. 45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void SetPluginInfo(const content::WebPluginInfo& plugin_info, 46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const PluginPrefs* plugin_prefs, 47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) metrics::SystemProfileProto::Plugin* plugin) { 48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin->set_name(base::UTF16ToUTF8(plugin_info.name)); 49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin->set_filename(plugin_info.path.BaseName().AsUTF8Unsafe()); 50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin->set_version(base::UTF16ToUTF8(plugin_info.version)); 51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin->set_is_pepper(plugin_info.is_pepper_plugin()); 52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (plugin_prefs) 53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin->set_is_disabled(!plugin_prefs->IsPluginEnabled(plugin_info)); 54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} // namespace 57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// This is used to quickly log stats from child process related notifications in 59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// PluginMetricsProvider::child_stats_buffer_. The buffer's contents are 60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// transferred out when Local State is periodically saved. The information is 61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// then reported to the UMA server on next launch. 62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)struct PluginMetricsProvider::ChildProcessStats { 63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public: 64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) explicit ChildProcessStats(int process_type) 65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) : process_launches(0), 66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) process_crashes(0), 67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) instances(0), 68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) loading_errors(0), 69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) process_type(process_type) {} 70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // This constructor is only used by the map to return some default value for 72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // an index for which no value has been assigned. 73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ChildProcessStats() 74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) : process_launches(0), 75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) process_crashes(0), 76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) instances(0), 77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) loading_errors(0), 78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) process_type(content::PROCESS_TYPE_UNKNOWN) {} 79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // The number of times that the given child process has been launched 81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int process_launches; 82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // The number of times that the given child process has crashed 84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int process_crashes; 85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // The number of instances of this child process that have been created. 87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // An instance is a DOM object rendered by this child process during a page 88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // load. 89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int instances; 90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // The number of times there was an error loading an instance of this child 92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // process. 93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int loading_errors; 94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int process_type; 96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)PluginMetricsProvider::PluginMetricsProvider(PrefService* local_state) 99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) : local_state_(local_state), 100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) weak_ptr_factory_(this) { 101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(local_state_); 102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) BrowserChildProcessObserver::Add(this); 104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)PluginMetricsProvider::~PluginMetricsProvider() { 107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) BrowserChildProcessObserver::Remove(this); 108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PluginMetricsProvider::GetPluginInformation( 111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::Closure& done_callback) { 112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::PluginService::GetInstance()->GetPlugins( 113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind(&PluginMetricsProvider::OnGotPlugins, 114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) done_callback)); 116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PluginMetricsProvider::ProvideSystemProfileMetrics( 119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) metrics::SystemProfileProto* system_profile_proto) { 120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PluginPrefs* plugin_prefs = GetPluginPrefs(); 121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (size_t i = 0; i < plugins_.size(); ++i) { 122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SetPluginInfo(plugins_[i], plugin_prefs, 123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) system_profile_proto->add_plugin()); 124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PluginMetricsProvider::ProvideStabilityMetrics( 128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) metrics::SystemProfileProto* system_profile_proto) { 129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::ListValue* plugin_stats_list = local_state_->GetList( 130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) prefs::kStabilityPluginStats); 131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!plugin_stats_list) 132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) metrics::SystemProfileProto::Stability* stability = 135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) system_profile_proto->mutable_stability(); 136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (base::ListValue::const_iterator iter = plugin_stats_list->begin(); 137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) iter != plugin_stats_list->end(); ++iter) { 138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!(*iter)->IsType(base::Value::TYPE_DICTIONARY)) { 139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) NOTREACHED(); 140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) continue; 141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::DictionaryValue* plugin_dict = 143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) static_cast<base::DictionaryValue*>(*iter); 144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Note that this search is potentially a quadratic operation, but given the 146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // low number of plugins installed on a "reasonable" setup, this should be 147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // fine. 148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // TODO(isherman): Verify that this does not show up as a hotspot in 149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // profiler runs. 150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const metrics::SystemProfileProto::Plugin* system_profile_plugin = NULL; 151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string plugin_name; 152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin_dict->GetString(prefs::kStabilityPluginName, &plugin_name); 153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (int i = 0; i < system_profile_proto->plugin_size(); ++i) { 154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (system_profile_proto->plugin(i).name() == plugin_name) { 155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) system_profile_plugin = &system_profile_proto->plugin(i); 156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!system_profile_plugin) { 161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) NOTREACHED(); 162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) continue; 163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) metrics::SystemProfileProto::Stability::PluginStability* plugin_stability = 166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) stability->add_plugin_stability(); 167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *plugin_stability->mutable_plugin() = *system_profile_plugin; 168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int launches = 0; 170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin_dict->GetInteger(prefs::kStabilityPluginLaunches, &launches); 171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (launches > 0) 172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin_stability->set_launch_count(launches); 173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int instances = 0; 175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin_dict->GetInteger(prefs::kStabilityPluginInstances, &instances); 176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (instances > 0) 177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin_stability->set_instance_count(instances); 178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int crashes = 0; 180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin_dict->GetInteger(prefs::kStabilityPluginCrashes, &crashes); 181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (crashes > 0) 182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin_stability->set_crash_count(crashes); 183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int loading_errors = 0; 185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin_dict->GetInteger(prefs::kStabilityPluginLoadingErrors, 186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) &loading_errors); 187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (loading_errors > 0) 188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin_stability->set_loading_error_count(loading_errors); 189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) local_state_->ClearPref(prefs::kStabilityPluginStats); 192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PluginMetricsProvider::RecordPluginChanges() { 195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ListPrefUpdate update(local_state_, prefs::kStabilityPluginStats); 196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::ListValue* plugins = update.Get(); 197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(plugins); 198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 199cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (base::ListValue::iterator value_iter = plugins->begin(); 200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) value_iter != plugins->end(); ++value_iter) { 201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!(*value_iter)->IsType(base::Value::TYPE_DICTIONARY)) { 202cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) NOTREACHED(); 203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) continue; 204cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::DictionaryValue* plugin_dict = 207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) static_cast<base::DictionaryValue*>(*value_iter); 208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string plugin_name; 209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin_dict->GetString(prefs::kStabilityPluginName, &plugin_name); 210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (plugin_name.empty()) { 211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) NOTREACHED(); 212cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) continue; 213cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // TODO(viettrungluu): remove conversions 216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::string16 name16 = base::UTF8ToUTF16(plugin_name); 217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (child_process_stats_buffer_.find(name16) == 218cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) child_process_stats_buffer_.end()) { 219cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) continue; 220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ChildProcessStats stats = child_process_stats_buffer_[name16]; 223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (stats.process_launches) { 224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int launches = 0; 225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin_dict->GetInteger(prefs::kStabilityPluginLaunches, &launches); 226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) launches += stats.process_launches; 227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin_dict->SetInteger(prefs::kStabilityPluginLaunches, launches); 228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (stats.process_crashes) { 230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int crashes = 0; 231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin_dict->GetInteger(prefs::kStabilityPluginCrashes, &crashes); 232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) crashes += stats.process_crashes; 233cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin_dict->SetInteger(prefs::kStabilityPluginCrashes, crashes); 234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 235cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (stats.instances) { 236cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int instances = 0; 237cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin_dict->GetInteger(prefs::kStabilityPluginInstances, &instances); 238cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) instances += stats.instances; 239cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin_dict->SetInteger(prefs::kStabilityPluginInstances, instances); 240cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 241cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (stats.loading_errors) { 242cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int loading_errors = 0; 243cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin_dict->GetInteger(prefs::kStabilityPluginLoadingErrors, 244cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) &loading_errors); 245cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) loading_errors += stats.loading_errors; 246cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin_dict->SetInteger(prefs::kStabilityPluginLoadingErrors, 247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) loading_errors); 248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 249cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 250cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) child_process_stats_buffer_.erase(name16); 251cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Now go through and add dictionaries for plugins that didn't already have 254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // reports in Local State. 255cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (std::map<base::string16, ChildProcessStats>::iterator cache_iter = 256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) child_process_stats_buffer_.begin(); 257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) cache_iter != child_process_stats_buffer_.end(); ++cache_iter) { 258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ChildProcessStats stats = cache_iter->second; 259cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Insert only plugins information into the plugins list. 261cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!IsPluginProcess(stats.process_type)) 262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) continue; 263cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 264cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // TODO(viettrungluu): remove conversion 265cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string plugin_name = base::UTF16ToUTF8(cache_iter->first); 266cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 267cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::DictionaryValue* plugin_dict = new base::DictionaryValue; 268cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 269cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin_dict->SetString(prefs::kStabilityPluginName, plugin_name); 270cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin_dict->SetInteger(prefs::kStabilityPluginLaunches, 271cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) stats.process_launches); 272cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin_dict->SetInteger(prefs::kStabilityPluginCrashes, 273cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) stats.process_crashes); 274cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin_dict->SetInteger(prefs::kStabilityPluginInstances, 275cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) stats.instances); 276cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin_dict->SetInteger(prefs::kStabilityPluginLoadingErrors, 277cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) stats.loading_errors); 278cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugins->Append(plugin_dict); 279cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 280cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) child_process_stats_buffer_.clear(); 281cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 282cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PluginMetricsProvider::LogPluginLoadingError( 284cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::FilePath& plugin_path) { 285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::WebPluginInfo plugin; 286cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool success = 287cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::PluginService::GetInstance()->GetPluginInfoByPath(plugin_path, 288cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) &plugin); 289cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(success); 290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ChildProcessStats& stats = child_process_stats_buffer_[plugin.name]; 291cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Initialize the type if this entry is new. 292cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (stats.process_type == content::PROCESS_TYPE_UNKNOWN) { 293cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // The plug-in process might not actually be of type PLUGIN (which means 294cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // NPAPI), but we only care that it is *a* plug-in process. 295cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) stats.process_type = content::PROCESS_TYPE_PLUGIN; 296cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else { 297cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(IsPluginProcess(stats.process_type)); 298cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 299cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) stats.loading_errors++; 300cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 301cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 302cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PluginMetricsProvider::SetPluginsForTesting( 303cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::vector<content::WebPluginInfo>& plugins) { 304cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugins_ = plugins; 305cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 306cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static 308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool PluginMetricsProvider::IsPluginProcess(int process_type) { 309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return (process_type == content::PROCESS_TYPE_PLUGIN || 310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) process_type == content::PROCESS_TYPE_PPAPI_PLUGIN || 311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) process_type == content::PROCESS_TYPE_PPAPI_BROKER); 312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 313cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static 315cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PluginMetricsProvider::RegisterPrefs(PrefRegistrySimple* registry) { 316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) registry->RegisterListPref(prefs::kStabilityPluginStats); 317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 318cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 319cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PluginMetricsProvider::OnGotPlugins( 320cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::Closure& done_callback, 321cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::vector<content::WebPluginInfo>& plugins) { 322cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugins_ = plugins; 323cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) done_callback.Run(); 324cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 325cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 326cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)PluginMetricsProvider::ChildProcessStats& 327cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)PluginMetricsProvider::GetChildProcessStats( 328cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const content::ChildProcessData& data) { 329cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::string16& child_name = data.name; 330cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!ContainsKey(child_process_stats_buffer_, child_name)) { 331cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) child_process_stats_buffer_[child_name] = 332cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ChildProcessStats(data.process_type); 333cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 334cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return child_process_stats_buffer_[child_name]; 335cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 336cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 337cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PluginMetricsProvider::BrowserChildProcessHostConnected( 338cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const content::ChildProcessData& data) { 339cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GetChildProcessStats(data).process_launches++; 340cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 341cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 342cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PluginMetricsProvider::BrowserChildProcessCrashed( 343cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const content::ChildProcessData& data) { 344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GetChildProcessStats(data).process_crashes++; 345cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PluginMetricsProvider::BrowserChildProcessInstanceCreated( 348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const content::ChildProcessData& data) { 349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GetChildProcessStats(data).instances++; 350cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 351