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 "content/public/common/content_client.h"
7 #include "content/public/common/content_constants.h"
8 #include "content/public/common/content_switches.h"
9 #include "content/public/common/pepper_plugin_info.h"
10 #include "content/public/renderer/content_renderer_client.h"
11 #include "content/public/test/render_view_test.h"
12 #include "content/renderer/pepper/pepper_webplugin_impl.h"
13 #include "content/renderer/pepper/plugin_instance_throttler_impl.h"
14 #include "content/renderer/pepper/plugin_module.h"
15 #include "content/renderer/pepper/renderer_ppapi_host_impl.h"
16 #include "content/renderer/render_frame_impl.h"
17 #include "content/test/test_content_client.h"
18 #include "ppapi/c/pp_errors.h"
19 #include "ppapi/c/ppb_core.h"
20 #include "ppapi/c/ppb_graphics_2d.h"
21 #include "ppapi/c/ppb_image_data.h"
22 #include "ppapi/c/ppb_instance.h"
23 #include "ppapi/c/ppp_instance.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 #include "third_party/WebKit/public/web/WebLocalFrame.h"
30 class PepperWebPluginImplBrowserTest
31 : public RenderViewTest
,
32 public PluginInstanceThrottler::Observer
{
34 PepperWebPluginImplBrowserTest()
35 : throttler_(nullptr),
36 throttle_engaged_(false),
41 void SetUp() override
{
42 base::CommandLine
& command_line
= *base::CommandLine::ForCurrentProcess();
43 command_line
.AppendSwitchASCII(
44 switches::kOverridePluginPowerSaverForTesting
, "always");
47 RenderViewTest::SetUp();
49 void TearDown() override
{
50 RenderViewTest::TearDown();
51 current_test_
= nullptr;
53 ContentClient
* CreateContentClient() override
{
54 return new MockContentClient
;
56 ContentRendererClient
* CreateContentRendererClient() override
{
57 return new MockContentRendererClient
;
60 // PluginInstanceThrottler::Observer implementation
61 void OnThrottleStateChange() override
{
62 if (throttler_
->IsThrottled())
63 throttle_engaged_
= true;
68 static const void* GetInterface(const char* name
) {
69 static PPP_Instance ppp_instance
= {
70 &PepperWebPluginImplBrowserTest::DidCreate
,
71 &PepperWebPluginImplBrowserTest::DidDestroy
,
72 &PepperWebPluginImplBrowserTest::DidChangeView
,
73 &PepperWebPluginImplBrowserTest::DidChangeFocus
,
74 &PepperWebPluginImplBrowserTest::HandleDocumentLoad
};
75 if (!strcmp(name
, PPP_INSTANCE_INTERFACE
))
79 static int InitializeModule(PP_Module module
,
80 PPB_GetInterface get_interface
) {
81 EXPECT_EQ(0, current_test_
->pp_module_
);
82 current_test_
->pp_module_
= module
;
83 ppb_core_
= static_cast<const PPB_Core
*>(get_interface(PPB_CORE_INTERFACE
));
84 ppb_graphics2d_
= static_cast<const PPB_Graphics2D
*>(
85 get_interface(PPB_GRAPHICS_2D_INTERFACE
));
86 ppb_image_data_
= static_cast<const PPB_ImageData
*>(
87 get_interface(PPB_IMAGEDATA_INTERFACE
));
89 static_cast<const PPB_Instance
*>(get_interface(PPB_INSTANCE_INTERFACE
));
92 static void ShutdownModule() {
93 EXPECT_NE(0, current_test_
->pp_module_
);
94 current_test_
->pp_module_
= 0;
97 static void DummyCallback(void*, int32_t) {}
99 void PaintSomething() {
100 PP_Size size
= {2, 1};
101 PP_Resource image
= ppb_image_data_
->Create(
102 pp_instance_
, ppb_image_data_
->GetNativeImageDataFormat(), &size
,
104 int32_t* pixels
= static_cast<int32_t*>(ppb_image_data_
->Map(image
));
105 pixels
[0] = 0xff000000;
106 pixels
[1] = 0xffffffff;
107 ppb_image_data_
->Unmap(image
);
108 ppb_graphics2d_
->ReplaceContents(graphics2d_
, image
);
109 PP_CompletionCallback callback
= {
110 &PepperWebPluginImplBrowserTest::DummyCallback
, nullptr, 0};
111 ppb_graphics2d_
->Flush(graphics2d_
, callback
);
112 ppb_core_
->ReleaseResource(image
);
115 // PPP_Instance implementation
116 static PP_Bool
DidCreate(PP_Instance instance
,
120 EXPECT_EQ(0, current_test_
->pp_instance_
);
121 current_test_
->pp_instance_
= instance
;
122 PP_Size size
= {2, 1};
123 current_test_
->graphics2d_
=
124 ppb_graphics2d_
->Create(instance
, &size
, PP_TRUE
);
125 ppb_instance_
->BindGraphics(instance
, current_test_
->graphics2d_
);
128 static void DidDestroy(PP_Instance instance
) {
129 EXPECT_NE(0, current_test_
->pp_instance_
);
130 current_test_
->PaintSomething();
131 ppb_core_
->ReleaseResource(current_test_
->graphics2d_
);
132 current_test_
->pp_instance_
= 0;
134 static void DidChangeView(PP_Instance
, PP_Resource
) {}
135 static void DidChangeFocus(PP_Instance
, PP_Bool
) {}
136 static PP_Bool
HandleDocumentLoad(PP_Instance
, PP_Resource
) {
140 static PepperPluginInfo
GetPluginInfo() {
141 PepperPluginInfo info
;
142 info
.is_internal
= true;
143 info
.path
= base::FilePath(FILE_PATH_LITERAL("internal-always-throttle"));
144 info
.name
= "Always Throttle";
145 info
.mime_types
.push_back(
146 WebPluginMimeType("test/always-throttle", "", ""));
147 info
.internal_entry_points
.get_interface
=
148 &PepperWebPluginImplBrowserTest::GetInterface
;
149 info
.internal_entry_points
.initialize_module
=
150 &PepperWebPluginImplBrowserTest::InitializeModule
;
151 info
.internal_entry_points
.shutdown_module
=
152 &PepperWebPluginImplBrowserTest::ShutdownModule
;
156 class MockContentClient
: public TestContentClient
{
158 void AddPepperPlugins(std::vector
<PepperPluginInfo
>* plugins
) override
{
159 plugins
->push_back(GetPluginInfo());
162 class MockContentRendererClient
: public ContentRendererClient
{
164 bool OverrideCreatePlugin(RenderFrame
* render_frame
,
165 blink::WebLocalFrame
* frame
,
166 const blink::WebPluginParams
& params
,
167 blink::WebPlugin
** plugin
) override
{
168 current_test_
->throttler_
= new PluginInstanceThrottlerImpl
;
169 current_test_
->throttler_
->AddObserver(current_test_
);
170 *plugin
= render_frame
->CreatePlugin(frame
,
171 GetPluginInfo().ToWebPluginInfo(), params
,
172 make_scoped_ptr(current_test_
->throttler_
));
177 PluginInstanceThrottlerImpl
* throttler_
;
178 bool throttle_engaged_
;
179 PP_Module pp_module_
;
180 PP_Instance pp_instance_
;
181 PP_Resource graphics2d_
;
182 static PepperWebPluginImplBrowserTest
* current_test_
;
183 static const PPB_Core
* ppb_core_
;
184 static const PPB_Graphics2D
* ppb_graphics2d_
;
185 static const PPB_ImageData
* ppb_image_data_
;
186 static const PPB_Instance
* ppb_instance_
;
188 PepperWebPluginImplBrowserTest
* PepperWebPluginImplBrowserTest::current_test_
;
189 const PPB_Core
* PepperWebPluginImplBrowserTest::ppb_core_
;
190 const PPB_Graphics2D
* PepperWebPluginImplBrowserTest::ppb_graphics2d_
;
191 const PPB_ImageData
* PepperWebPluginImplBrowserTest::ppb_image_data_
;
192 const PPB_Instance
* PepperWebPluginImplBrowserTest::ppb_instance_
;
194 // This test simulates the behavior of a plugin that emits new frames during
195 // destruction. The throttler shouldn't engage and create a placeholder for
196 // a to-be destroyed plugin in such case. See crbug.com/483068
197 TEST_F(PepperWebPluginImplBrowserTest
, NotEngageThrottleDuringDestroy
) {
198 LoadHTML("<!DOCTYPE html><object type='test/always-throttle'></object>");
199 EXPECT_NE(0, pp_instance_
);
201 EXPECT_EQ(0, pp_instance_
);
202 EXPECT_FALSE(throttle_engaged_
);
205 } // unnamed namespace
207 } // namespace content