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 "ppapi/shared_impl/ppapi_switches.h"
18 #include "third_party/WebKit/public/web/WebInputEvent.h"
19 #include "ui/base/window_open_disposition.h"
20 #include "ui/gfx/geometry/point.h"
24 std::string
RunTestScript(base::StringPiece test_script
,
25 content::WebContents
* contents
,
26 const std::string
& element_id
) {
27 std::string script
= base::StringPrintf(
28 "var plugin = window.document.getElementById('%s');"
29 "if (plugin === undefined ||"
30 " (plugin.nodeName !== 'OBJECT' && plugin.nodeName !== 'EMBED')) {"
31 " window.domAutomationController.send('error');"
35 element_id
.c_str(), test_script
.data());
38 content::ExecuteScriptAndExtractString(contents
, script
, &result
));
42 // This also tests that we have JavaScript access to the underlying plugin.
43 bool PluginLoaded(content::WebContents
* contents
, const char* element_id
) {
44 std::string result
= RunTestScript(
45 "if (plugin.postMessage === undefined) {"
46 " window.domAutomationController.send('poster_only');"
48 " window.domAutomationController.send('plugin_loaded');"
50 contents
, element_id
);
51 EXPECT_NE("error", result
);
52 return result
== "plugin_loaded";
55 // Also waits for the placeholder UI overlay to finish loading.
56 void VerifyPluginIsThrottled(content::WebContents
* contents
,
57 const char* element_id
) {
58 std::string result
= RunTestScript(
59 "function handleEvent(event) {"
60 " if (event.data.isPeripheral && event.data.isThrottled && "
61 " event.data.isHiddenForPlaceholder) {"
62 " window.domAutomationController.send('throttled');"
63 " plugin.removeEventListener('message', handleEvent);"
66 "plugin.addEventListener('message', handleEvent);"
67 "if (plugin.postMessage !== undefined) {"
68 " plugin.postMessage('getPowerSaverStatus');"
70 contents
, element_id
);
71 EXPECT_EQ("throttled", result
);
73 // Page should continue to have JavaScript access to all throttled plugins.
74 EXPECT_TRUE(PluginLoaded(contents
, element_id
));
77 void VerifyPluginMarkedEssential(content::WebContents
* contents
,
78 const char* element_id
) {
79 std::string result
= RunTestScript(
80 "function handleEvent(event) {"
81 " if (event.data.isPeripheral === false) {"
82 " window.domAutomationController.send('essential');"
83 " plugin.removeEventListener('message', handleEvent);"
86 "plugin.addEventListener('message', handleEvent);"
87 "if (plugin.postMessage !== undefined) {"
88 " plugin.postMessage('getPowerSaverStatus');"
90 contents
, element_id
);
91 EXPECT_EQ("essential", result
);
92 EXPECT_TRUE(PluginLoaded(contents
, element_id
));
97 class PluginPowerSaverBrowserTest
: public InProcessBrowserTest
{
99 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
100 command_line
->AppendSwitch(switches::kEnablePluginPowerSaver
);
101 command_line
->AppendSwitch(switches::kEnablePepperTesting
);
102 command_line
->AppendSwitch(switches::kEnablePluginPlaceholderTesting
);
103 command_line
->AppendSwitchASCII(
104 switches::kOverridePluginPowerSaverForTesting
, "ignore-list");
106 ASSERT_TRUE(ppapi::RegisterPowerSaverTestPlugin(command_line
));
110 void LoadHTML(const char* html
) {
111 std::string url_str
= "data:text/html;charset=utf-8,";
112 url_str
.append(html
);
113 ui_test_utils::NavigateToURL(browser(), GURL(url_str
));
114 EXPECT_TRUE(content::WaitForRenderFrameReady(
115 GetActiveWebContents()->GetMainFrame()));
118 content::WebContents
* GetActiveWebContents() {
119 return browser()->tab_strip_model()->GetActiveWebContents();
122 // This sends a simulated click at |point| and waits for test plugin to send
123 // a status message indicating that it is essential. The test plugin sends a
124 // status message during:
125 // - Plugin creation, to handle a plugin freshly created from a poster.
126 // - Peripheral status change.
127 // - In response to the explicit 'getPowerSaverStatus' request, in case the
128 // test has missed the above two events.
129 void SimulateClickAndAwaitMarkedEssential(const char* element_id
,
130 const gfx::Point
& point
) {
131 // Waits for the placeholder to be ready to be clicked first.
132 std::string result
= RunTestScript(
133 "function handleEvent(event) {"
134 " if (event.data === 'placeholderLoaded') {"
135 " window.domAutomationController.send('ready');"
136 " plugin.removeEventListener('message', handleEvent);"
139 "plugin.addEventListener('message', handleEvent);"
140 "if (plugin.hasAttribute('placeholderLoaded')) {"
141 " window.domAutomationController.send('ready');"
142 " plugin.removeEventListener('message', handleEvent);"
144 GetActiveWebContents(), element_id
);
145 ASSERT_EQ("ready", result
);
147 content::SimulateMouseClickAt(GetActiveWebContents(), 0 /* modifiers */,
148 blink::WebMouseEvent::ButtonLeft
, point
);
150 VerifyPluginMarkedEssential(GetActiveWebContents(), element_id
);
154 IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest
, SmallSameOrigin
) {
156 "<object id='plugin' data='fake.swf' "
157 " type='application/x-ppapi-tests' width='400' height='100'>"
159 VerifyPluginMarkedEssential(GetActiveWebContents(), "plugin");
162 IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest
, SmallCrossOrigin
) {
164 "<object id='plugin' data='http://otherorigin.com/fake.swf' "
165 " type='application/x-ppapi-tests' width='400' height='100'>"
167 VerifyPluginIsThrottled(GetActiveWebContents(), "plugin");
169 SimulateClickAndAwaitMarkedEssential("plugin", gfx::Point(50, 50));
172 IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest
, LargeCrossOrigin
) {
174 "<object id='large' data='http://otherorigin.com/fake.swf' "
175 " type='application/x-ppapi-tests' width='400' height='500'>"
177 "<object id='medium_16_9' data='http://otherorigin.com/fake.swf' "
178 " type='application/x-ppapi-tests' width='480' height='270'>"
180 VerifyPluginMarkedEssential(GetActiveWebContents(), "large");
181 VerifyPluginMarkedEssential(GetActiveWebContents(), "medium_16_9");
184 IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest
,
185 LargePluginsPeripheralWhenPosterSpecified
) {
187 "<object id='plugin_src' type='application/x-ppapi-tests' "
188 " width='400' height='500' poster='snapshot1x.png'></object>"
189 "<object id='plugin_srcset' type='application/x-ppapi-tests' "
190 " width='400' height='500' "
191 " poster='snapshot1x.png 1x, snapshot2x.png 2x'></object>"
192 "<object id='plugin_legacy_syntax' type='application/x-ppapi-tests' "
193 " width='400' height='500'>"
194 " <param name='poster' value='snapshot1x.png 1x, snapshot2x.png 2x'>"
196 "<embed id='plugin_embed_src' type='application/x-ppapi-tests' "
197 " width='400' height='500' poster='snapshot1x.png'></embed>"
198 "<embed id='plugin_embed_srcset' type='application/x-ppapi-tests' "
199 " width='400' height='500'"
200 " poster='snapshot1x.png 1x, snapshot2x.png 2x'></embed>");
202 EXPECT_FALSE(PluginLoaded(GetActiveWebContents(), "plugin_src"));
203 EXPECT_FALSE(PluginLoaded(GetActiveWebContents(), "plugin_srcset"));
204 EXPECT_FALSE(PluginLoaded(GetActiveWebContents(), "plugin_legacy_syntax"));
205 EXPECT_FALSE(PluginLoaded(GetActiveWebContents(), "plugin_embed_src"));
206 EXPECT_FALSE(PluginLoaded(GetActiveWebContents(), "plugin_embed_srcset"));
209 IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest
,
210 PluginMarkedEssentialAfterPosterClicked
) {
212 "<object id='plugin' type='application/x-ppapi-tests' "
213 " width='400' height='100' poster='snapshot1x.png'></object>");
214 EXPECT_FALSE(PluginLoaded(GetActiveWebContents(), "plugin"));
216 SimulateClickAndAwaitMarkedEssential("plugin", gfx::Point(50, 50));
219 IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest
, OriginWhitelisting
) {
221 "<object id='plugin1' data='http://otherorigin.com/fake1.swf' "
222 " type='application/x-ppapi-tests' width='400' height='100'></object>"
223 "<object id='plugin2' data='http://otherorigin.com/fake2.swf' "
224 " type='application/x-ppapi-tests' width='400' height='500'>"
226 VerifyPluginMarkedEssential(GetActiveWebContents(), "plugin1");
227 VerifyPluginMarkedEssential(GetActiveWebContents(), "plugin2");
230 IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest
, LargeCrossOriginObscured
) {
232 "<div id='container' "
233 " style='width: 400px; height: 100px; overflow: hidden;'>"
234 " <object id='plugin' data='http://otherorigin.com/fake.swf' "
235 " type='application/x-ppapi-tests' width='400' height='500'>"
238 VerifyPluginIsThrottled(GetActiveWebContents(), "plugin");
240 // Test that's unthrottled if it is unobscured.
242 "var container = window.document.getElementById('container');"
243 "container.setAttribute('style', 'width: 400px; height: 400px;');";
244 ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(), script
));
245 VerifyPluginMarkedEssential(GetActiveWebContents(), "plugin");
248 IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest
, ExpandingSmallPlugin
) {
250 "<object id='plugin' data='http://otherorigin.com/fake.swf' "
251 " type='application/x-ppapi-tests' width='400' height='80'></object>");
252 VerifyPluginIsThrottled(GetActiveWebContents(), "plugin");
254 std::string script
= "window.document.getElementById('plugin').height = 400;";
255 ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(), script
));
256 VerifyPluginMarkedEssential(GetActiveWebContents(), "plugin");
259 IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest
, BackgroundTabPlugins
) {
260 std::string url_str
=
261 "data:text/html;charset=utf-8,"
262 "<object id='same_origin' type='application/x-ppapi-tests'></object>"
263 "<object id='small_cross_origin' data='http://otherorigin.com/fake1.swf' "
264 " type='application/x-ppapi-tests' width='400' height='100'></object>";
265 ui_test_utils::NavigateToURLWithDisposition(
266 browser(), GURL(url_str
), NEW_BACKGROUND_TAB
,
267 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION
);
269 ASSERT_EQ(2, browser()->tab_strip_model()->count());
270 content::WebContents
* background_contents
=
271 browser()->tab_strip_model()->GetWebContentsAt(1);
273 content::WaitForRenderFrameReady(background_contents
->GetMainFrame()));
275 EXPECT_FALSE(PluginLoaded(background_contents
, "same_origin"));
276 EXPECT_FALSE(PluginLoaded(background_contents
, "small_cross_origin"));
278 browser()->tab_strip_model()->SelectNextTab();
279 EXPECT_EQ(background_contents
, GetActiveWebContents());
281 VerifyPluginMarkedEssential(background_contents
, "same_origin");
282 VerifyPluginIsThrottled(background_contents
, "small_cross_origin");
285 IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest
, ZoomIndependent
) {
286 ui_zoom::ZoomController::FromWebContents(GetActiveWebContents())
289 "<object id='plugin' data='http://otherorigin.com/fake.swf' "
290 " type='application/x-ppapi-tests' width='400' height='200'>"
292 VerifyPluginIsThrottled(GetActiveWebContents(), "plugin");