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