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) 1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid PluginMetricsProvider::ClearSavedStabilityMetrics() { 2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci local_state_->ClearPref(prefs::kStabilityPluginStats); 2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 20346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Saves plugin-related updates from the in-object buffer to Local State 20446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// for retrieval next time we send a Profile log (generally next launch). 20546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void PluginMetricsProvider::RecordCurrentState() { 206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ListPrefUpdate update(local_state_, prefs::kStabilityPluginStats); 207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::ListValue* plugins = update.Get(); 208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(plugins); 209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (base::ListValue::iterator value_iter = plugins->begin(); 211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) value_iter != plugins->end(); ++value_iter) { 212cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!(*value_iter)->IsType(base::Value::TYPE_DICTIONARY)) { 213cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) NOTREACHED(); 214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) continue; 215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::DictionaryValue* plugin_dict = 218cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) static_cast<base::DictionaryValue*>(*value_iter); 219cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string plugin_name; 220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin_dict->GetString(prefs::kStabilityPluginName, &plugin_name); 221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (plugin_name.empty()) { 222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) NOTREACHED(); 223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) continue; 224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // TODO(viettrungluu): remove conversions 227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::string16 name16 = base::UTF8ToUTF16(plugin_name); 228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (child_process_stats_buffer_.find(name16) == 229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) child_process_stats_buffer_.end()) { 230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) continue; 231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 233cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ChildProcessStats stats = child_process_stats_buffer_[name16]; 234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (stats.process_launches) { 235cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int launches = 0; 236cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin_dict->GetInteger(prefs::kStabilityPluginLaunches, &launches); 237cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) launches += stats.process_launches; 238cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin_dict->SetInteger(prefs::kStabilityPluginLaunches, launches); 239cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 240cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (stats.process_crashes) { 241cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int crashes = 0; 242cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin_dict->GetInteger(prefs::kStabilityPluginCrashes, &crashes); 243cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) crashes += stats.process_crashes; 244cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin_dict->SetInteger(prefs::kStabilityPluginCrashes, crashes); 245cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 246cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (stats.instances) { 247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int instances = 0; 248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin_dict->GetInteger(prefs::kStabilityPluginInstances, &instances); 249cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) instances += stats.instances; 250cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin_dict->SetInteger(prefs::kStabilityPluginInstances, instances); 251cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (stats.loading_errors) { 253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int loading_errors = 0; 254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin_dict->GetInteger(prefs::kStabilityPluginLoadingErrors, 255cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) &loading_errors); 256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) loading_errors += stats.loading_errors; 257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin_dict->SetInteger(prefs::kStabilityPluginLoadingErrors, 258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) loading_errors); 259cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 261cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) child_process_stats_buffer_.erase(name16); 262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 263cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 264cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Now go through and add dictionaries for plugins that didn't already have 265cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // reports in Local State. 266cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (std::map<base::string16, ChildProcessStats>::iterator cache_iter = 267cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) child_process_stats_buffer_.begin(); 268cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) cache_iter != child_process_stats_buffer_.end(); ++cache_iter) { 269cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ChildProcessStats stats = cache_iter->second; 270cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 271cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Insert only plugins information into the plugins list. 272cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!IsPluginProcess(stats.process_type)) 273cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) continue; 274cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 275cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // TODO(viettrungluu): remove conversion 276cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string plugin_name = base::UTF16ToUTF8(cache_iter->first); 277cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 278cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::DictionaryValue* plugin_dict = new base::DictionaryValue; 279cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 280cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin_dict->SetString(prefs::kStabilityPluginName, plugin_name); 281cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin_dict->SetInteger(prefs::kStabilityPluginLaunches, 282cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) stats.process_launches); 283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin_dict->SetInteger(prefs::kStabilityPluginCrashes, 284cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) stats.process_crashes); 285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin_dict->SetInteger(prefs::kStabilityPluginInstances, 286cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) stats.instances); 287cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugin_dict->SetInteger(prefs::kStabilityPluginLoadingErrors, 288cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) stats.loading_errors); 289cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugins->Append(plugin_dict); 290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 291cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) child_process_stats_buffer_.clear(); 292cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 293cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 294cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PluginMetricsProvider::LogPluginLoadingError( 295cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::FilePath& plugin_path) { 296cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::WebPluginInfo plugin; 297cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool success = 298cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::PluginService::GetInstance()->GetPluginInfoByPath(plugin_path, 299cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) &plugin); 300cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(success); 301cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ChildProcessStats& stats = child_process_stats_buffer_[plugin.name]; 302cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Initialize the type if this entry is new. 303cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (stats.process_type == content::PROCESS_TYPE_UNKNOWN) { 304cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // The plug-in process might not actually be of type PLUGIN (which means 305cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // NPAPI), but we only care that it is *a* plug-in process. 306cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) stats.process_type = content::PROCESS_TYPE_PLUGIN; 307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else { 308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(IsPluginProcess(stats.process_type)); 309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) stats.loading_errors++; 3115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) RecordCurrentStateWithDelay(kRecordStateDelayMs); 312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 313cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PluginMetricsProvider::SetPluginsForTesting( 315cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::vector<content::WebPluginInfo>& plugins) { 316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugins_ = plugins; 317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 318cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 319cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static 320cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool PluginMetricsProvider::IsPluginProcess(int process_type) { 321cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return (process_type == content::PROCESS_TYPE_PLUGIN || 322cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) process_type == content::PROCESS_TYPE_PPAPI_PLUGIN || 323cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) process_type == content::PROCESS_TYPE_PPAPI_BROKER); 324cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 325cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 326cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static 327cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PluginMetricsProvider::RegisterPrefs(PrefRegistrySimple* registry) { 328cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) registry->RegisterListPref(prefs::kStabilityPluginStats); 329cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 330cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 331cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PluginMetricsProvider::OnGotPlugins( 332cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::Closure& done_callback, 333cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::vector<content::WebPluginInfo>& plugins) { 334cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) plugins_ = plugins; 335cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) done_callback.Run(); 336cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 337cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 338cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)PluginMetricsProvider::ChildProcessStats& 339cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)PluginMetricsProvider::GetChildProcessStats( 340cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const content::ChildProcessData& data) { 341cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::string16& child_name = data.name; 342cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!ContainsKey(child_process_stats_buffer_, child_name)) { 343cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) child_process_stats_buffer_[child_name] = 344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ChildProcessStats(data.process_type); 345cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return child_process_stats_buffer_[child_name]; 347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PluginMetricsProvider::BrowserChildProcessHostConnected( 350cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const content::ChildProcessData& data) { 351cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GetChildProcessStats(data).process_launches++; 3525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) RecordCurrentStateWithDelay(kRecordStateDelayMs); 353cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 354cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 355cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PluginMetricsProvider::BrowserChildProcessCrashed( 356cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const content::ChildProcessData& data) { 357cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GetChildProcessStats(data).process_crashes++; 3585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) RecordCurrentStateWithDelay(kRecordStateDelayMs); 359cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 360cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 361cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PluginMetricsProvider::BrowserChildProcessInstanceCreated( 362cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const content::ChildProcessData& data) { 363cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GetChildProcessStats(data).instances++; 3645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) RecordCurrentStateWithDelay(kRecordStateDelayMs); 3655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 3665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool PluginMetricsProvider::RecordCurrentStateWithDelay(int delay_sec) { 3685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (weak_ptr_factory_.HasWeakPtrs()) 3695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 3705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::MessageLoopProxy::current()->PostDelayedTask( 3725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) FROM_HERE, 3735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&PluginMetricsProvider::RecordCurrentState, 3745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) weak_ptr_factory_.GetWeakPtr()), 3755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::TimeDelta::FromMilliseconds(delay_sec)); 3765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return true; 3775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 3785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool PluginMetricsProvider::RecordCurrentStateIfPending() { 3805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!weak_ptr_factory_.HasWeakPtrs()) 3815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 3825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) weak_ptr_factory_.InvalidateWeakPtrs(); 3845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) RecordCurrentState(); 3855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return true; 386cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 387