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 "content/public/common/content_switches.h"
14 #include "content/public/test/browser_test_utils.h"
15 #include "content/public/test/ppapi_test_utils.h"
16 #include "ppapi/shared_impl/ppapi_switches.h"
17 #include "third_party/WebKit/public/web/WebInputEvent.h"
18 #include "ui/base/window_open_disposition.h"
19 #include "ui/gfx/geometry/point.h"
23 std::string
RunTestScript(base::StringPiece test_script
,
24 content::WebContents
* contents
,
25 const std::string
& element_id
) {
26 std::string script
= base::StringPrintf(
27 "var plugin = window.document.getElementById('%s');"
28 "if (plugin === undefined ||"
29 " (plugin.nodeName !== 'OBJECT' && plugin.nodeName !== 'EMBED')) {"
30 " window.domAutomationController.send('error');"
34 element_id
.c_str(), test_script
.data());
37 content::ExecuteScriptAndExtractString(contents
, script
, &result
));
41 // This also tests that we have JavaScript access to the underlying plugin.
42 bool PluginLoaded(content::WebContents
* contents
, const char* element_id
) {
43 std::string result
= RunTestScript(
44 "if (plugin.postMessage === undefined) {"
45 " window.domAutomationController.send('poster_only');"
47 " window.domAutomationController.send('plugin_loaded');"
49 contents
, element_id
);
50 EXPECT_NE("error", result
);
51 return result
== "plugin_loaded";
54 // Also waits for the placeholder UI overlay to finish loading.
55 void VerifyPluginIsThrottled(content::WebContents
* contents
,
56 const char* element_id
) {
57 std::string result
= RunTestScript(
58 "function handleEvent(event) {"
59 " if (event.data.isPeripheral && event.data.isThrottled && "
60 " event.data.isHiddenForPlaceholder) {"
61 " window.domAutomationController.send('throttled');"
62 " plugin.removeEventListener('message', handleEvent);"
65 "plugin.addEventListener('message', handleEvent);"
66 "if (plugin.postMessage !== undefined) {"
67 " plugin.postMessage('getPowerSaverStatus');"
69 contents
, element_id
);
70 EXPECT_EQ("throttled", result
);
72 // Page should continue to have JavaScript access to all throttled plugins.
73 EXPECT_TRUE(PluginLoaded(contents
, element_id
));
76 void VerifyPluginMarkedEssential(content::WebContents
* contents
,
77 const char* element_id
) {
78 std::string result
= RunTestScript(
79 "function handleEvent(event) {"
80 " if (event.data.isPeripheral === false) {"
81 " window.domAutomationController.send('essential');"
82 " plugin.removeEventListener('message', handleEvent);"
85 "plugin.addEventListener('message', handleEvent);"
86 "if (plugin.postMessage !== undefined) {"
87 " plugin.postMessage('getPowerSaverStatus');"
89 contents
, element_id
);
90 EXPECT_EQ("essential", result
);
91 EXPECT_TRUE(PluginLoaded(contents
, element_id
));
96 class PluginPowerSaverBrowserTest
: virtual public InProcessBrowserTest
{
98 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
99 command_line
->AppendSwitch(switches::kEnablePluginPowerSaver
);
100 command_line
->AppendSwitch(switches::kEnablePepperTesting
);
101 command_line
->AppendSwitch(switches::kEnablePluginPlaceholderTesting
);
102 command_line
->AppendSwitchASCII(
103 switches::kOverridePluginPowerSaverForTesting
, "ignore-list");
105 ASSERT_TRUE(ppapi::RegisterPowerSaverTestPlugin(command_line
));
109 void LoadHTML(const char* html
) {
110 std::string url_str
= "data:text/html;charset=utf-8,";
111 url_str
.append(html
);
112 ui_test_utils::NavigateToURL(browser(), GURL(url_str
));
113 EXPECT_TRUE(content::WaitForRenderFrameReady(
114 GetActiveWebContents()->GetMainFrame()));
117 content::WebContents
* GetActiveWebContents() {
118 return browser()->tab_strip_model()->GetActiveWebContents();
121 // This sends a simulated click at |point| and waits for test plugin to send
122 // a status message indicating that it is essential. The test plugin sends a
123 // status message during:
124 // - Plugin creation, to handle a plugin freshly created from a poster.
125 // - Peripheral status change.
126 // - In response to the explicit 'getPowerSaverStatus' request, in case the
127 // test has missed the above two events.
128 void SimulateClickAndAwaitMarkedEssential(const char* element_id
,
129 const gfx::Point
& point
) {
130 // Waits for the placeholder to be ready to be clicked first.
131 std::string result
= RunTestScript(
132 "function handleEvent(event) {"
133 " if (event.data === 'placeholderLoaded') {"
134 " window.domAutomationController.send('ready');"
135 " plugin.removeEventListener('message', handleEvent);"
138 "plugin.addEventListener('message', handleEvent);"
139 "if (plugin.hasAttribute('placeholderLoaded')) {"
140 " window.domAutomationController.send('ready');"
141 " plugin.removeEventListener('message', handleEvent);"
143 GetActiveWebContents(), element_id
);
144 ASSERT_EQ("ready", result
);
146 content::SimulateMouseClickAt(GetActiveWebContents(), 0 /* modifiers */,
147 blink::WebMouseEvent::ButtonLeft
, point
);
149 VerifyPluginMarkedEssential(GetActiveWebContents(), element_id
);
153 IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest
, SmallSameOrigin
) {
155 "<object id='plugin' data='fake.swf' "
156 " type='application/x-ppapi-tests' width='400' height='100'>"
158 VerifyPluginMarkedEssential(GetActiveWebContents(), "plugin");
161 IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest
, SmallCrossOrigin
) {
163 "<object id='plugin' data='http://otherorigin.com/fake.swf' "
164 " type='application/x-ppapi-tests' width='400' height='100'>"
166 VerifyPluginIsThrottled(GetActiveWebContents(), "plugin");
168 SimulateClickAndAwaitMarkedEssential("plugin", gfx::Point(50, 50));
171 IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest
, LargeCrossOrigin
) {
173 "<object id='large' data='http://otherorigin.com/fake.swf' "
174 " type='application/x-ppapi-tests' width='400' height='500'>"
176 "<object id='medium_16_9' data='http://otherorigin.com/fake.swf' "
177 " type='application/x-ppapi-tests' width='480' height='270'>"
179 VerifyPluginMarkedEssential(GetActiveWebContents(), "large");
180 VerifyPluginMarkedEssential(GetActiveWebContents(), "medium_16_9");
183 IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest
,
184 LargePluginsPeripheralWhenPosterSpecified
) {
186 "<object id='plugin_src' type='application/x-ppapi-tests' "
187 " width='400' height='500' poster='snapshot1x.png'></object>"
188 "<object id='plugin_srcset' type='application/x-ppapi-tests' "
189 " width='400' height='500' "
190 " poster='snapshot1x.png 1x, snapshot2x.png 2x'></object>"
191 "<object id='plugin_legacy_syntax' type='application/x-ppapi-tests' "
192 " width='400' height='500'>"
193 " <param name='poster' value='snapshot1x.png 1x, snapshot2x.png 2x'>"
195 "<embed id='plugin_embed_src' type='application/x-ppapi-tests' "
196 " width='400' height='500' poster='snapshot1x.png'></embed>"
197 "<embed id='plugin_embed_srcset' type='application/x-ppapi-tests' "
198 " width='400' height='500'"
199 " poster='snapshot1x.png 1x, snapshot2x.png 2x'></embed>");
201 EXPECT_FALSE(PluginLoaded(GetActiveWebContents(), "plugin_src"));
202 EXPECT_FALSE(PluginLoaded(GetActiveWebContents(), "plugin_srcset"));
203 EXPECT_FALSE(PluginLoaded(GetActiveWebContents(), "plugin_legacy_syntax"));
204 EXPECT_FALSE(PluginLoaded(GetActiveWebContents(), "plugin_embed_src"));
205 EXPECT_FALSE(PluginLoaded(GetActiveWebContents(), "plugin_embed_srcset"));
208 IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest
,
209 PluginMarkedEssentialAfterPosterClicked
) {
211 "<object id='plugin' type='application/x-ppapi-tests' "
212 " width='400' height='100' poster='snapshot1x.png'></object>");
213 EXPECT_FALSE(PluginLoaded(GetActiveWebContents(), "plugin"));
215 SimulateClickAndAwaitMarkedEssential("plugin", gfx::Point(50, 50));
218 IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest
, OriginWhitelisting
) {
220 "<object id='plugin1' data='http://otherorigin.com/fake1.swf' "
221 " type='application/x-ppapi-tests' width='400' height='100'></object>"
222 "<object id='plugin2' data='http://otherorigin.com/fake2.swf' "
223 " type='application/x-ppapi-tests' width='400' height='500'>"
225 VerifyPluginMarkedEssential(GetActiveWebContents(), "plugin1");
226 VerifyPluginMarkedEssential(GetActiveWebContents(), "plugin2");
229 IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest
, LargeCrossOriginObscured
) {
231 "<div id='container' "
232 " style='width: 400px; height: 100px; overflow: hidden;'>"
233 " <object id='plugin' data='http://otherorigin.com/fake.swf' "
234 " type='application/x-ppapi-tests' width='400' height='500'>"
237 VerifyPluginIsThrottled(GetActiveWebContents(), "plugin");
239 // Test that's unthrottled if it is unobscured.
241 "var container = window.document.getElementById('container');"
242 "container.setAttribute('style', 'width: 400px; height: 400px;');";
243 ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(), script
));
244 VerifyPluginMarkedEssential(GetActiveWebContents(), "plugin");
247 IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest
, ExpandingSmallPlugin
) {
249 "<object id='plugin' data='http://otherorigin.com/fake.swf' "
250 " type='application/x-ppapi-tests' width='400' height='80'></object>");
251 VerifyPluginIsThrottled(GetActiveWebContents(), "plugin");
253 std::string script
= "window.document.getElementById('plugin').height = 400;";
254 ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(), script
));
255 VerifyPluginMarkedEssential(GetActiveWebContents(), "plugin");
258 IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest
, BackgroundTabPlugins
) {
259 std::string url_str
=
260 "data:text/html;charset=utf-8,"
261 "<object id='same_origin' type='application/x-ppapi-tests'></object>"
262 "<object id='small_cross_origin' data='http://otherorigin.com/fake1.swf' "
263 " type='application/x-ppapi-tests' width='400' height='100'></object>";
264 ui_test_utils::NavigateToURLWithDisposition(
265 browser(), GURL(url_str
), NEW_BACKGROUND_TAB
,
266 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION
);
268 ASSERT_EQ(2, browser()->tab_strip_model()->count());
269 content::WebContents
* background_contents
=
270 browser()->tab_strip_model()->GetWebContentsAt(1);
272 content::WaitForRenderFrameReady(background_contents
->GetMainFrame()));
274 EXPECT_FALSE(PluginLoaded(background_contents
, "same_origin"));
275 EXPECT_FALSE(PluginLoaded(background_contents
, "small_cross_origin"));
277 browser()->tab_strip_model()->SelectNextTab();
278 EXPECT_EQ(background_contents
, GetActiveWebContents());
280 VerifyPluginMarkedEssential(background_contents
, "same_origin");
281 VerifyPluginIsThrottled(background_contents
, "small_cross_origin");