1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/metrics/plugin_metrics_provider.h" 6 7#include <string> 8 9#include "base/basictypes.h" 10#include "base/prefs/pref_service.h" 11#include "base/prefs/scoped_user_pref_update.h" 12#include "base/prefs/testing_pref_service.h" 13#include "base/run_loop.h" 14#include "base/strings/utf_string_conversions.h" 15#include "chrome/common/pref_names.h" 16#include "components/metrics/proto/system_profile.pb.h" 17#include "content/public/browser/child_process_data.h" 18#include "content/public/common/process_type.h" 19#include "content/public/common/webplugininfo.h" 20#include "content/public/test/test_browser_thread_bundle.h" 21#include "testing/gtest/include/gtest/gtest.h" 22 23namespace { 24 25content::WebPluginInfo CreateFakePluginInfo( 26 const std::string& name, 27 const base::FilePath::CharType* path, 28 const std::string& version, 29 bool is_pepper) { 30 content::WebPluginInfo plugin(base::UTF8ToUTF16(name), 31 base::FilePath(path), 32 base::UTF8ToUTF16(version), 33 base::string16()); 34 if (is_pepper) 35 plugin.type = content::WebPluginInfo::PLUGIN_TYPE_PEPPER_IN_PROCESS; 36 else 37 plugin.type = content::WebPluginInfo::PLUGIN_TYPE_NPAPI; 38 return plugin; 39} 40 41class PluginMetricsProviderTest : public ::testing::Test { 42 protected: 43 PluginMetricsProviderTest() 44 : prefs_(new TestingPrefServiceSimple) { 45 PluginMetricsProvider::RegisterPrefs(prefs()->registry()); 46 } 47 48 TestingPrefServiceSimple* prefs() { 49 return prefs_.get(); 50 } 51 52 private: 53 scoped_ptr<TestingPrefServiceSimple> prefs_; 54 55 DISALLOW_COPY_AND_ASSIGN(PluginMetricsProviderTest); 56}; 57 58} // namespace 59 60TEST_F(PluginMetricsProviderTest, IsPluginProcess) { 61 EXPECT_TRUE(PluginMetricsProvider::IsPluginProcess( 62 content::PROCESS_TYPE_PLUGIN)); 63 EXPECT_TRUE(PluginMetricsProvider::IsPluginProcess( 64 content::PROCESS_TYPE_PPAPI_PLUGIN)); 65 EXPECT_FALSE(PluginMetricsProvider::IsPluginProcess( 66 content::PROCESS_TYPE_GPU)); 67} 68 69TEST_F(PluginMetricsProviderTest, Plugins) { 70 content::TestBrowserThreadBundle thread_bundle; 71 72 PluginMetricsProvider provider(prefs()); 73 74 std::vector<content::WebPluginInfo> plugins; 75 plugins.push_back(CreateFakePluginInfo("p1", FILE_PATH_LITERAL("p1.plugin"), 76 "1.5", true)); 77 plugins.push_back(CreateFakePluginInfo("p2", FILE_PATH_LITERAL("p2.plugin"), 78 "2.0", false)); 79 provider.SetPluginsForTesting(plugins); 80 81 metrics::SystemProfileProto system_profile; 82 provider.ProvideSystemProfileMetrics(&system_profile); 83 84 ASSERT_EQ(2, system_profile.plugin_size()); 85 EXPECT_EQ("p1", system_profile.plugin(0).name()); 86 EXPECT_EQ("p1.plugin", system_profile.plugin(0).filename()); 87 EXPECT_EQ("1.5", system_profile.plugin(0).version()); 88 EXPECT_TRUE(system_profile.plugin(0).is_pepper()); 89 EXPECT_EQ("p2", system_profile.plugin(1).name()); 90 EXPECT_EQ("p2.plugin", system_profile.plugin(1).filename()); 91 EXPECT_EQ("2.0", system_profile.plugin(1).version()); 92 EXPECT_FALSE(system_profile.plugin(1).is_pepper()); 93 94 // Now set some plugin stability stats for p2 and verify they're recorded. 95 scoped_ptr<base::DictionaryValue> plugin_dict(new base::DictionaryValue); 96 plugin_dict->SetString(prefs::kStabilityPluginName, "p2"); 97 plugin_dict->SetInteger(prefs::kStabilityPluginLaunches, 1); 98 plugin_dict->SetInteger(prefs::kStabilityPluginCrashes, 2); 99 plugin_dict->SetInteger(prefs::kStabilityPluginInstances, 3); 100 plugin_dict->SetInteger(prefs::kStabilityPluginLoadingErrors, 4); 101 { 102 ListPrefUpdate update(prefs(), prefs::kStabilityPluginStats); 103 update.Get()->Append(plugin_dict.release()); 104 } 105 106 provider.ProvideStabilityMetrics(&system_profile); 107 108 const metrics::SystemProfileProto_Stability& stability = 109 system_profile.stability(); 110 ASSERT_EQ(1, stability.plugin_stability_size()); 111 EXPECT_EQ("p2", stability.plugin_stability(0).plugin().name()); 112 EXPECT_EQ("p2.plugin", stability.plugin_stability(0).plugin().filename()); 113 EXPECT_EQ("2.0", stability.plugin_stability(0).plugin().version()); 114 EXPECT_FALSE(stability.plugin_stability(0).plugin().is_pepper()); 115 EXPECT_EQ(1, stability.plugin_stability(0).launch_count()); 116 EXPECT_EQ(2, stability.plugin_stability(0).crash_count()); 117 EXPECT_EQ(3, stability.plugin_stability(0).instance_count()); 118 EXPECT_EQ(4, stability.plugin_stability(0).loading_error_count()); 119} 120 121TEST_F(PluginMetricsProviderTest, RecordCurrentStateWithDelay) { 122 content::TestBrowserThreadBundle thread_bundle; 123 124 PluginMetricsProvider provider(prefs()); 125 126 int delay_ms = 10; 127 EXPECT_TRUE(provider.RecordCurrentStateWithDelay(delay_ms)); 128 EXPECT_FALSE(provider.RecordCurrentStateWithDelay(delay_ms)); 129 130 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(delay_ms)); 131 base::RunLoop().RunUntilIdle(); 132 133 EXPECT_TRUE(provider.RecordCurrentStateWithDelay(delay_ms)); 134} 135 136TEST_F(PluginMetricsProviderTest, RecordCurrentStateIfPending) { 137 content::TestBrowserThreadBundle thread_bundle; 138 139 PluginMetricsProvider provider(prefs()); 140 141 // First there should be no need to force RecordCurrentState. 142 EXPECT_FALSE(provider.RecordCurrentStateIfPending()); 143 144 // After delayed task is posted RecordCurrentStateIfPending should return 145 // true. 146 int delay_ms = 100000; 147 EXPECT_TRUE(provider.RecordCurrentStateWithDelay(delay_ms)); 148 EXPECT_TRUE(provider.RecordCurrentStateIfPending()); 149 150 // If RecordCurrentStateIfPending was successful then we should be able to 151 // post a new delayed task. 152 EXPECT_TRUE(provider.RecordCurrentStateWithDelay(delay_ms)); 153} 154 155TEST_F(PluginMetricsProviderTest, ProvideStabilityMetricsWhenPendingTask) { 156 content::TestBrowserThreadBundle thread_bundle; 157 158 PluginMetricsProvider provider(prefs()); 159 160 // Create plugin information for testing. 161 std::vector<content::WebPluginInfo> plugins; 162 plugins.push_back(CreateFakePluginInfo("p1", FILE_PATH_LITERAL("p1.plugin"), 163 "1.5", true)); 164 provider.SetPluginsForTesting(plugins); 165 metrics::SystemProfileProto system_profile; 166 provider.ProvideSystemProfileMetrics(&system_profile); 167 168 // Increase number of created instances which should also start a delayed 169 // task. 170 content::ChildProcessData child_process_data(content::PROCESS_TYPE_PLUGIN); 171 child_process_data.name = base::UTF8ToUTF16("p1"); 172 provider.BrowserChildProcessInstanceCreated(child_process_data); 173 174 // Call ProvideStabilityMetrics to check that it will force pending tasks to 175 // be executed immediately. 176 provider.ProvideStabilityMetrics(&system_profile); 177 178 // Check current number of instances created. 179 const metrics::SystemProfileProto_Stability& stability = 180 system_profile.stability(); 181 EXPECT_EQ(1, stability.plugin_stability(0).instance_count()); 182} 183