Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / plugins / plugin_power_saver_browsertest.cc
blob333720d38cf3728abeb7a5bffab2b9efd6ca013e
1 // Copyright 2015 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/command_line.h"
6 #include "base/strings/string_piece.h"
7 #include "base/strings/stringprintf.h"
8 #include "chrome/browser/ui/browser.h"
9 #include "chrome/browser/ui/tabs/tab_strip_model.h"
10 #include "chrome/common/chrome_switches.h"
11 #include "chrome/test/base/in_process_browser_test.h"
12 #include "chrome/test/base/ui_test_utils.h"
13 #include "components/ui/zoom/zoom_controller.h"
14 #include "content/public/common/content_switches.h"
15 #include "content/public/test/browser_test_utils.h"
16 #include "content/public/test/ppapi_test_utils.h"
17 #include "net/test/embedded_test_server/embedded_test_server.h"
18 #include "net/test/embedded_test_server/http_request.h"
19 #include "net/test/embedded_test_server/http_response.h"
20 #include "ppapi/shared_impl/ppapi_switches.h"
21 #include "third_party/WebKit/public/web/WebInputEvent.h"
22 #include "ui/base/window_open_disposition.h"
23 #include "ui/gfx/geometry/point.h"
25 namespace {
27 std::string RunTestScript(base::StringPiece test_script,
28 content::WebContents* contents,
29 const std::string& element_id) {
30 std::string script = base::StringPrintf(
31 "var plugin = window.document.getElementById('%s');"
32 "if (plugin === undefined ||"
33 " (plugin.nodeName !== 'OBJECT' && plugin.nodeName !== 'EMBED')) {"
34 " window.domAutomationController.send('error');"
35 "} else {"
36 " %s"
37 "}",
38 element_id.c_str(), test_script.data());
39 std::string result;
40 EXPECT_TRUE(
41 content::ExecuteScriptAndExtractString(contents, script, &result));
42 return result;
45 // This also tests that we have JavaScript access to the underlying plugin.
46 bool PluginLoaded(content::WebContents* contents, const char* element_id) {
47 std::string result = RunTestScript(
48 "if (plugin.postMessage === undefined) {"
49 " window.domAutomationController.send('poster_only');"
50 "} else {"
51 " window.domAutomationController.send('plugin_loaded');"
52 "}",
53 contents, element_id);
54 EXPECT_NE("error", result);
55 return result == "plugin_loaded";
58 // Also waits for the placeholder UI overlay to finish loading.
59 void VerifyPluginIsThrottled(content::WebContents* contents,
60 const char* element_id) {
61 std::string result = RunTestScript(
62 "function handleEvent(event) {"
63 " if (event.data.isPeripheral && event.data.isThrottled && "
64 " event.data.isHiddenForPlaceholder) {"
65 " window.domAutomationController.send('throttled');"
66 " plugin.removeEventListener('message', handleEvent);"
67 " }"
68 "}"
69 "plugin.addEventListener('message', handleEvent);"
70 "if (plugin.postMessage !== undefined) {"
71 " plugin.postMessage('getPowerSaverStatus');"
72 "}",
73 contents, element_id);
74 EXPECT_EQ("throttled", result);
76 // Page should continue to have JavaScript access to all throttled plugins.
77 EXPECT_TRUE(PluginLoaded(contents, element_id));
80 void VerifyPluginMarkedEssential(content::WebContents* contents,
81 const char* element_id) {
82 std::string result = RunTestScript(
83 "function handleEvent(event) {"
84 " if (event.data.isPeripheral === false) {"
85 " window.domAutomationController.send('essential');"
86 " plugin.removeEventListener('message', handleEvent);"
87 " }"
88 "}"
89 "plugin.addEventListener('message', handleEvent);"
90 "if (plugin.postMessage !== undefined) {"
91 " plugin.postMessage('getPowerSaverStatus');"
92 "}",
93 contents, element_id);
94 EXPECT_EQ("essential", result);
95 EXPECT_TRUE(PluginLoaded(contents, element_id));
98 scoped_ptr<net::test_server::HttpResponse> RespondWithHTML(
99 const std::string& html,
100 const net::test_server::HttpRequest& request) {
101 scoped_ptr<net::test_server::BasicHttpResponse> response(
102 new net::test_server::BasicHttpResponse());
103 response->set_content_type("text/html");
104 response->set_content(html);
105 return response.Pass();
108 } // namespace
110 class PluginPowerSaverBrowserTest : public InProcessBrowserTest {
111 public:
112 void SetUpOnMainThread() override {
113 InProcessBrowserTest::SetUpOnMainThread();
114 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
117 void SetUpCommandLine(base::CommandLine* command_line) override {
118 command_line->AppendSwitch(switches::kEnablePluginPowerSaver);
119 command_line->AppendSwitch(switches::kEnablePepperTesting);
120 command_line->AppendSwitch(switches::kEnablePluginPlaceholderTesting);
121 command_line->AppendSwitchASCII(
122 switches::kOverridePluginPowerSaverForTesting, "ignore-list");
124 ASSERT_TRUE(ppapi::RegisterPowerSaverTestPlugin(command_line));
127 protected:
128 void LoadHTML(const std::string& html) {
129 ASSERT_TRUE(embedded_test_server()->Started());
130 embedded_test_server()->RegisterRequestHandler(
131 base::Bind(&RespondWithHTML, html));
132 ui_test_utils::NavigateToURL(browser(), embedded_test_server()->base_url());
133 EXPECT_TRUE(content::WaitForRenderFrameReady(
134 GetActiveWebContents()->GetMainFrame()));
137 content::WebContents* GetActiveWebContents() {
138 return browser()->tab_strip_model()->GetActiveWebContents();
141 // This sends a simulated click at |point| and waits for test plugin to send
142 // a status message indicating that it is essential. The test plugin sends a
143 // status message during:
144 // - Plugin creation, to handle a plugin freshly created from a poster.
145 // - Peripheral status change.
146 // - In response to the explicit 'getPowerSaverStatus' request, in case the
147 // test has missed the above two events.
148 void SimulateClickAndAwaitMarkedEssential(const char* element_id,
149 const gfx::Point& point) {
150 // Waits for the placeholder to be ready to be clicked first.
151 std::string result = RunTestScript(
152 "function handleEvent(event) {"
153 " if (event.data === 'placeholderLoaded') {"
154 " window.domAutomationController.send('ready');"
155 " plugin.removeEventListener('message', handleEvent);"
156 " }"
158 "plugin.addEventListener('message', handleEvent);"
159 "if (plugin.hasAttribute('placeholderLoaded')) {"
160 " window.domAutomationController.send('ready');"
161 " plugin.removeEventListener('message', handleEvent);"
162 "}",
163 GetActiveWebContents(), element_id);
164 ASSERT_EQ("ready", result);
166 content::SimulateMouseClickAt(GetActiveWebContents(), 0 /* modifiers */,
167 blink::WebMouseEvent::ButtonLeft, point);
169 VerifyPluginMarkedEssential(GetActiveWebContents(), element_id);
173 IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest, SmallSameOrigin) {
174 LoadHTML(
175 "<object id='plugin' data='fake.swf' "
176 " type='application/x-ppapi-tests' width='400' height='100'>"
177 "</object>");
178 VerifyPluginMarkedEssential(GetActiveWebContents(), "plugin");
181 IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest, SmallCrossOrigin) {
182 LoadHTML(
183 "<object id='plugin' data='http://otherorigin.com/fake.swf' "
184 " type='application/x-ppapi-tests' width='400' height='100'>"
185 "</object>");
186 VerifyPluginIsThrottled(GetActiveWebContents(), "plugin");
188 SimulateClickAndAwaitMarkedEssential("plugin", gfx::Point(50, 50));
191 IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest, LargeCrossOrigin) {
192 LoadHTML(
193 "<object id='large' data='http://otherorigin.com/fake.swf' "
194 " type='application/x-ppapi-tests' width='400' height='500'>"
195 "</object>"
196 "<object id='medium_16_9' data='http://otherorigin.com/fake.swf' "
197 " type='application/x-ppapi-tests' width='480' height='270'>"
198 "</object>");
199 VerifyPluginMarkedEssential(GetActiveWebContents(), "large");
200 VerifyPluginMarkedEssential(GetActiveWebContents(), "medium_16_9");
203 IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest,
204 LargePluginsPeripheralWhenPosterSpecified) {
205 LoadHTML(
206 "<object id='plugin_src' type='application/x-ppapi-tests' "
207 " width='400' height='500' poster='snapshot1x.png'></object>"
208 "<object id='plugin_srcset' type='application/x-ppapi-tests' "
209 " width='400' height='500' "
210 " poster='snapshot1x.png 1x, snapshot2x.png 2x'></object>"
211 "<object id='plugin_legacy_syntax' type='application/x-ppapi-tests' "
212 " width='400' height='500'>"
213 " <param name='poster' value='snapshot1x.png 1x, snapshot2x.png 2x'>"
214 "</object>"
215 "<embed id='plugin_embed_src' type='application/x-ppapi-tests' "
216 " width='400' height='500' poster='snapshot1x.png'></embed>"
217 "<embed id='plugin_embed_srcset' type='application/x-ppapi-tests' "
218 " width='400' height='500'"
219 " poster='snapshot1x.png 1x, snapshot2x.png 2x'></embed>");
221 EXPECT_FALSE(PluginLoaded(GetActiveWebContents(), "plugin_src"));
222 EXPECT_FALSE(PluginLoaded(GetActiveWebContents(), "plugin_srcset"));
223 EXPECT_FALSE(PluginLoaded(GetActiveWebContents(), "plugin_legacy_syntax"));
224 EXPECT_FALSE(PluginLoaded(GetActiveWebContents(), "plugin_embed_src"));
225 EXPECT_FALSE(PluginLoaded(GetActiveWebContents(), "plugin_embed_srcset"));
228 IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest,
229 PluginMarkedEssentialAfterPosterClicked) {
230 LoadHTML(
231 "<object id='plugin' type='application/x-ppapi-tests' "
232 " width='400' height='100' poster='snapshot1x.png'></object>");
233 EXPECT_FALSE(PluginLoaded(GetActiveWebContents(), "plugin"));
235 SimulateClickAndAwaitMarkedEssential("plugin", gfx::Point(50, 50));
238 IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest, OriginWhitelisting) {
239 LoadHTML(
240 "<object id='plugin1' data='http://otherorigin.com/fake1.swf' "
241 " type='application/x-ppapi-tests' width='400' height='100'></object>"
242 "<object id='plugin2' data='http://otherorigin.com/fake2.swf' "
243 " type='application/x-ppapi-tests' width='400' height='500'>"
244 "</object>");
245 VerifyPluginMarkedEssential(GetActiveWebContents(), "plugin1");
246 VerifyPluginMarkedEssential(GetActiveWebContents(), "plugin2");
249 IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest, LargeCrossOriginObscured) {
250 LoadHTML(
251 "<div id='container' "
252 " style='width: 400px; height: 100px; overflow: hidden;'>"
253 " <object id='plugin' data='http://otherorigin.com/fake.swf' "
254 " type='application/x-ppapi-tests' width='400' height='500'>"
255 " </object>"
256 "</div>");
257 VerifyPluginIsThrottled(GetActiveWebContents(), "plugin");
259 // Test that's unthrottled if it is unobscured.
260 std::string script =
261 "var container = window.document.getElementById('container');"
262 "container.setAttribute('style', 'width: 400px; height: 400px;');";
263 ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(), script));
264 VerifyPluginMarkedEssential(GetActiveWebContents(), "plugin");
267 IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest, ExpandingSmallPlugin) {
268 LoadHTML(
269 "<object id='plugin' data='http://otherorigin.com/fake.swf' "
270 " type='application/x-ppapi-tests' width='400' height='80'></object>");
271 VerifyPluginIsThrottled(GetActiveWebContents(), "plugin");
273 std::string script = "window.document.getElementById('plugin').height = 400;";
274 ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(), script));
275 VerifyPluginMarkedEssential(GetActiveWebContents(), "plugin");
278 IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest, BackgroundTabPlugins) {
279 std::string html =
280 "<object id='same_origin' data='fake.swf' "
281 " type='application/x-ppapi-tests'></object>"
282 "<object id='small_cross_origin' data='http://otherorigin.com/fake1.swf' "
283 " type='application/x-ppapi-tests' width='400' height='100'></object>";
284 embedded_test_server()->RegisterRequestHandler(
285 base::Bind(&RespondWithHTML, html));
286 ui_test_utils::NavigateToURLWithDisposition(
287 browser(), embedded_test_server()->base_url(), NEW_BACKGROUND_TAB,
288 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
290 ASSERT_EQ(2, browser()->tab_strip_model()->count());
291 content::WebContents* background_contents =
292 browser()->tab_strip_model()->GetWebContentsAt(1);
293 EXPECT_TRUE(
294 content::WaitForRenderFrameReady(background_contents->GetMainFrame()));
296 EXPECT_FALSE(PluginLoaded(background_contents, "same_origin"));
297 EXPECT_FALSE(PluginLoaded(background_contents, "small_cross_origin"));
299 browser()->tab_strip_model()->SelectNextTab();
300 EXPECT_EQ(background_contents, GetActiveWebContents());
302 VerifyPluginMarkedEssential(background_contents, "same_origin");
303 VerifyPluginIsThrottled(background_contents, "small_cross_origin");
306 IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest, ZoomIndependent) {
307 ui_zoom::ZoomController::FromWebContents(GetActiveWebContents())
308 ->SetZoomLevel(4.0);
309 LoadHTML(
310 "<object id='plugin' data='http://otherorigin.com/fake.swf' "
311 " type='application/x-ppapi-tests' width='400' height='200'>"
312 "</object>");
313 VerifyPluginIsThrottled(GetActiveWebContents(), "plugin");