Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / extensions / api / tab_capture / tab_capture_performancetest.cc
blobeae6004b23bee127fb94db0367ddbb24f21533f9
1 // Copyright 2013 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.
5 #include "base/basictypes.h"
6 #include "base/command_line.h"
7 #include "base/strings/stringprintf.h"
8 #include "base/test/trace_event_analyzer.h"
9 #include "base/win/windows_version.h"
10 #include "chrome/browser/extensions/extension_apitest.h"
11 #include "chrome/browser/extensions/extension_service.h"
12 #include "chrome/browser/extensions/tab_helper.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h"
15 #include "chrome/common/chrome_switches.h"
16 #include "chrome/common/chrome_version_info.h"
17 #include "chrome/test/base/test_launcher_utils.h"
18 #include "chrome/test/base/test_switches.h"
19 #include "chrome/test/base/tracing.h"
20 #include "content/public/common/content_switches.h"
21 #include "extensions/common/feature_switch.h"
22 #include "extensions/common/features/base_feature_provider.h"
23 #include "extensions/common/features/complex_feature.h"
24 #include "extensions/common/features/feature.h"
25 #include "extensions/common/features/simple_feature.h"
26 #include "extensions/common/switches.h"
27 #include "extensions/test/extension_test_message_listener.h"
28 #include "testing/gtest/include/gtest/gtest.h"
29 #include "testing/perf/perf_test.h"
30 #include "ui/compositor/compositor_switches.h"
31 #include "ui/gl/gl_switches.h"
33 namespace {
35 const char kExtensionId[] = "ddchlicdkolnonkihahngkmmmjnjlkkf";
37 enum TestFlags {
38 kUseGpu = 1 << 0, // Only execute test if --enable-gpu was given
39 // on the command line. This is required for
40 // tests that run on GPU.
41 kForceGpuComposited = 1 << 1, // Force the test to use the compositor.
42 kDisableVsync = 1 << 2, // Do not limit framerate to vertical refresh.
43 // when on GPU, nor to 60hz when not on GPU.
44 kTestThroughWebRTC = 1 << 3, // Send captured frames through webrtc
45 kSmallWindow = 1 << 4, // 1 = 800x600, 0 = 2000x1000
47 kScaleQualityMask = 3 << 5, // two bits select which scaling quality
48 kScaleQualityDefault = 0 << 5, // to use on aura.
49 kScaleQualityFast = 1 << 5,
50 kScaleQualityGood = 2 << 5,
51 kScaleQualityBest = 3 << 5,
54 class TabCapturePerformanceTest
55 : public ExtensionApiTest,
56 public testing::WithParamInterface<int> {
57 public:
58 TabCapturePerformanceTest() {}
60 bool HasFlag(TestFlags flag) const {
61 return (GetParam() & flag) == flag;
64 bool IsGpuAvailable() const {
65 return base::CommandLine::ForCurrentProcess()->HasSwitch("enable-gpu");
68 std::string ScalingMethod() const {
69 switch (GetParam() & kScaleQualityMask) {
70 case kScaleQualityFast:
71 return "fast";
72 case kScaleQualityGood:
73 return "good";
74 case kScaleQualityBest:
75 return "best";
76 default:
77 return "";
81 std::string GetSuffixForTestFlags() {
82 std::string suffix;
83 if (HasFlag(kForceGpuComposited))
84 suffix += "_comp";
85 if (HasFlag(kUseGpu))
86 suffix += "_gpu";
87 if (HasFlag(kDisableVsync))
88 suffix += "_novsync";
89 if (HasFlag(kTestThroughWebRTC))
90 suffix += "_webrtc";
91 if (!ScalingMethod().empty())
92 suffix += "_scale" + ScalingMethod();
93 if (HasFlag(kSmallWindow))
94 suffix += "_small";
95 return suffix;
98 void SetUp() override {
99 EnablePixelOutput();
100 ExtensionApiTest::SetUp();
103 void SetUpCommandLine(base::CommandLine* command_line) override {
104 if (!ScalingMethod().empty()) {
105 command_line->AppendSwitchASCII(switches::kTabCaptureUpscaleQuality,
106 ScalingMethod());
107 command_line->AppendSwitchASCII(switches::kTabCaptureDownscaleQuality,
108 ScalingMethod());
111 // Some of the tests may launch http requests through JSON or AJAX
112 // which causes a security error (cross domain request) when the page
113 // is loaded from the local file system ( file:// ). The following switch
114 // fixes that error.
115 command_line->AppendSwitch(switches::kAllowFileAccessFromFiles);
117 if (HasFlag(kSmallWindow)) {
118 command_line->AppendSwitchASCII(switches::kWindowSize, "800,600");
119 } else {
120 command_line->AppendSwitchASCII(switches::kWindowSize, "2000,1500");
123 if (!HasFlag(kUseGpu))
124 command_line->AppendSwitch(switches::kDisableGpu);
126 if (HasFlag(kDisableVsync))
127 command_line->AppendSwitch(switches::kDisableGpuVsync);
129 command_line->AppendSwitchASCII(
130 extensions::switches::kWhitelistedExtensionID,
131 kExtensionId);
132 ExtensionApiTest::SetUpCommandLine(command_line);
135 bool PrintResults(trace_analyzer::TraceAnalyzer *analyzer,
136 const std::string& test_name,
137 const std::string& event_name,
138 const std::string& unit) {
139 trace_analyzer::TraceEventVector events;
140 trace_analyzer::Query query =
141 trace_analyzer::Query::EventNameIs(event_name) &&
142 (trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_BEGIN) ||
143 trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_COMPLETE) ||
144 trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_BEGIN) ||
145 trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_FLOW_BEGIN) ||
146 trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_INSTANT));
147 analyzer->FindEvents(query, &events);
148 if (events.size() < 20) {
149 LOG(ERROR) << "Not enough events of type " << event_name << " found ("
150 << events.size() << ").";
151 return false;
154 // Ignore some events for startup/setup/caching.
155 trace_analyzer::TraceEventVector rate_events(events.begin() + 3,
156 events.end() - 3);
157 trace_analyzer::RateStats stats;
158 if (!GetRateStats(rate_events, &stats, NULL)) {
159 LOG(ERROR) << "GetRateStats failed";
160 return false;
162 double mean_ms = stats.mean_us / 1000.0;
163 double std_dev_ms = stats.standard_deviation_us / 1000.0;
164 std::string mean_and_error = base::StringPrintf("%f,%f", mean_ms,
165 std_dev_ms);
166 perf_test::PrintResultMeanAndError(test_name,
167 GetSuffixForTestFlags(),
168 event_name,
169 mean_and_error,
170 unit,
171 true);
172 return true;
175 void RunTest(const std::string& test_name) {
176 if (HasFlag(kUseGpu) && !IsGpuAvailable()) {
177 LOG(WARNING) <<
178 "Test skipped: requires gpu. Pass --enable-gpu on the command "
179 "line if use of GPU is desired.";
180 return;
183 std::string json_events;
184 ASSERT_TRUE(tracing::BeginTracing("gpu,gpu.capture"));
185 std::string page = "performance.html";
186 page += HasFlag(kTestThroughWebRTC) ? "?WebRTC=1" : "?WebRTC=0";
187 // Ideally we'd like to run a higher capture rate when vsync is disabled,
188 // but libjingle currently doesn't allow that.
189 // page += HasFlag(kDisableVsync) ? "&fps=300" : "&fps=30";
190 page += "&fps=60";
191 ASSERT_TRUE(RunExtensionSubtest("tab_capture", page)) << message_;
192 ASSERT_TRUE(tracing::EndTracing(&json_events));
193 scoped_ptr<trace_analyzer::TraceAnalyzer> analyzer;
194 analyzer.reset(trace_analyzer::TraceAnalyzer::Create(json_events));
196 // The printed result will be the average time between frames in the
197 // browser window.
198 bool gpu_frames = PrintResults(
199 analyzer.get(),
200 test_name,
201 "RenderWidget::DidCommitAndDrawCompositorFrame",
202 "ms");
203 EXPECT_TRUE(gpu_frames);
205 // This prints out the average time between capture events.
206 // As the capture frame rate is capped at 30fps, this score
207 // cannot get any better than (lower) 33.33 ms.
208 // TODO(ericrk): Remove the "Capture" result once we are confident that
209 // "CaptureSucceeded" is giving the coverage we want. crbug.com/489817
210 EXPECT_TRUE(PrintResults(analyzer.get(),
211 test_name,
212 "Capture",
213 "ms"));
215 // Also track the CaptureSucceeded event. Capture only indicates that a
216 // capture was requested, but this capture may later be aborted without
217 // running. CaptureSucceeded tracks successful frame captures.
218 EXPECT_TRUE(
219 PrintResults(analyzer.get(), test_name, "CaptureSucceeded", "ms"));
223 } // namespace
225 IN_PROC_BROWSER_TEST_P(TabCapturePerformanceTest, Performance) {
226 RunTest("TabCapturePerformance");
229 // Note: First argument is optional and intentionally left blank.
230 // (it's a prefix for the generated test cases)
231 INSTANTIATE_TEST_CASE_P(
233 TabCapturePerformanceTest,
234 testing::Values(
236 kUseGpu | kForceGpuComposited,
237 kDisableVsync,
238 kDisableVsync | kUseGpu | kForceGpuComposited,
239 kTestThroughWebRTC,
240 kTestThroughWebRTC | kUseGpu | kForceGpuComposited,
241 kTestThroughWebRTC | kDisableVsync,
242 kTestThroughWebRTC | kDisableVsync | kUseGpu | kForceGpuComposited));
244 #if defined(USE_AURA)
245 // TODO(hubbe):
246 // These are temporary tests for the purpose of determining what the
247 // appropriate scaling quality is. Once that has been determined,
248 // these tests will be removed.
250 const int kScalingTestBase =
251 kTestThroughWebRTC | kDisableVsync | kUseGpu | kForceGpuComposited;
253 INSTANTIATE_TEST_CASE_P(
254 ScalingTests,
255 TabCapturePerformanceTest,
256 testing::Values(
257 kScalingTestBase | kScaleQualityFast,
258 kScalingTestBase | kScaleQualityGood,
259 kScalingTestBase | kScaleQualityBest,
260 kScalingTestBase | kScaleQualityFast | kSmallWindow,
261 kScalingTestBase | kScaleQualityGood | kSmallWindow,
262 kScalingTestBase | kScaleQualityBest | kSmallWindow));
264 #endif // USE_AURA