Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / content / renderer / browser_plugin / browser_plugin_browsertest.cc
blob69f1a6e6ffe78ed63793499bf1b4e1648b783ea3
1 // Copyright (c) 2012 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 "content/renderer/browser_plugin/browser_plugin_browsertest.h"
7 #include "base/debug/leak_annotations.h"
8 #include "base/files/file_path.h"
9 #include "base/memory/singleton.h"
10 #include "base/path_service.h"
11 #include "base/pickle.h"
12 #include "content/public/common/content_constants.h"
13 #include "content/public/renderer/content_renderer_client.h"
14 #include "content/renderer/browser_plugin/browser_plugin.h"
15 #include "content/renderer/browser_plugin/browser_plugin_manager_factory.h"
16 #include "content/renderer/browser_plugin/mock_browser_plugin.h"
17 #include "content/renderer/browser_plugin/mock_browser_plugin_manager.h"
18 #include "content/renderer/render_thread_impl.h"
19 #include "content/renderer/renderer_webkitplatformsupport_impl.h"
20 #include "skia/ext/platform_canvas.h"
21 #include "third_party/WebKit/public/platform/WebCursorInfo.h"
22 #include "third_party/WebKit/public/web/WebInputEvent.h"
23 #include "third_party/WebKit/public/web/WebLocalFrame.h"
24 #include "third_party/WebKit/public/web/WebScriptSource.h"
26 namespace content {
28 namespace {
29 const char kHTMLForBrowserPluginObject[] =
30 "<object id='browserplugin' width='640px' height='480px'"
31 " src='foo' type='%s'></object>"
32 "<script>document.querySelector('object').nonExistentAttribute;</script>";
34 const char kHTMLForSourcelessPluginObject[] =
35 "<object id='browserplugin' width='640px' height='480px' type='%s'>";
37 std::string GetHTMLForBrowserPluginObject() {
38 return base::StringPrintf(kHTMLForBrowserPluginObject,
39 kBrowserPluginMimeType);
42 } // namespace
44 // Test factory for creating test instances of BrowserPluginManager.
45 class TestBrowserPluginManagerFactory : public BrowserPluginManagerFactory {
46 public:
47 virtual MockBrowserPluginManager* CreateBrowserPluginManager(
48 RenderViewImpl* render_view) OVERRIDE {
49 return new MockBrowserPluginManager(render_view);
52 // Singleton getter.
53 static TestBrowserPluginManagerFactory* GetInstance() {
54 return Singleton<TestBrowserPluginManagerFactory>::get();
57 protected:
58 TestBrowserPluginManagerFactory() {}
59 virtual ~TestBrowserPluginManagerFactory() {}
61 private:
62 // For Singleton.
63 friend struct DefaultSingletonTraits<TestBrowserPluginManagerFactory>;
65 DISALLOW_COPY_AND_ASSIGN(TestBrowserPluginManagerFactory);
68 BrowserPluginTest::BrowserPluginTest() {}
70 BrowserPluginTest::~BrowserPluginTest() {}
72 void BrowserPluginTest::SetUp() {
73 BrowserPluginManager::set_factory_for_testing(
74 TestBrowserPluginManagerFactory::GetInstance());
75 content::RenderViewTest::SetUp();
78 void BrowserPluginTest::TearDown() {
79 BrowserPluginManager::set_factory_for_testing(
80 TestBrowserPluginManagerFactory::GetInstance());
81 #if defined(LEAK_SANITIZER)
82 // Do this before shutting down V8 in RenderViewTest::TearDown().
83 // http://crbug.com/328552
84 __lsan_do_leak_check();
85 #endif
86 RenderViewTest::TearDown();
89 std::string BrowserPluginTest::ExecuteScriptAndReturnString(
90 const std::string& script) {
91 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
92 v8::Handle<v8::Value> value = GetMainFrame()->executeScriptAndReturnValue(
93 blink::WebScriptSource(blink::WebString::fromUTF8(script.c_str())));
94 if (value.IsEmpty() || !value->IsString())
95 return std::string();
97 v8::Local<v8::String> v8_str = value->ToString();
98 int length = v8_str->Utf8Length() + 1;
99 scoped_ptr<char[]> str(new char[length]);
100 v8_str->WriteUtf8(str.get(), length);
101 return str.get();
104 int BrowserPluginTest::ExecuteScriptAndReturnInt(
105 const std::string& script) {
106 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
107 v8::Handle<v8::Value> value = GetMainFrame()->executeScriptAndReturnValue(
108 blink::WebScriptSource(blink::WebString::fromUTF8(script.c_str())));
109 if (value.IsEmpty() || !value->IsInt32())
110 return 0;
112 return value->Int32Value();
115 // A return value of false means that a value was not present. The return value
116 // of the script is stored in |result|
117 bool BrowserPluginTest::ExecuteScriptAndReturnBool(
118 const std::string& script, bool* result) {
119 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
120 v8::Handle<v8::Value> value = GetMainFrame()->executeScriptAndReturnValue(
121 blink::WebScriptSource(blink::WebString::fromUTF8(script.c_str())));
122 if (value.IsEmpty() || !value->IsBoolean())
123 return false;
125 *result = value->BooleanValue();
126 return true;
129 MockBrowserPlugin* BrowserPluginTest::GetCurrentPlugin() {
130 BrowserPluginHostMsg_Attach_Params params;
131 return GetCurrentPluginWithAttachParams(&params);
134 MockBrowserPlugin* BrowserPluginTest::GetCurrentPluginWithAttachParams(
135 BrowserPluginHostMsg_Attach_Params* params) {
136 MockBrowserPlugin* browser_plugin = static_cast<MockBrowserPluginManager*>(
137 browser_plugin_manager())->last_plugin();
138 if (!browser_plugin)
139 return NULL;
141 browser_plugin->Attach();
143 int instance_id = 0;
144 const IPC::Message* msg =
145 browser_plugin_manager()->sink().GetUniqueMessageMatching(
146 BrowserPluginHostMsg_Attach::ID);
147 if (!msg)
148 return NULL;
150 PickleIterator iter(*msg);
151 if (!iter.ReadInt(&instance_id))
152 return NULL;
154 if (!IPC::ParamTraits<BrowserPluginHostMsg_Attach_Params>::Read(
155 msg, &iter, params)) {
156 return NULL;
159 browser_plugin->OnAttachACK(instance_id);
160 return browser_plugin;
163 // This test verifies that an initial resize occurs when we instantiate the
164 // browser plugin.
165 TEST_F(BrowserPluginTest, InitialResize) {
166 LoadHTML(GetHTMLForBrowserPluginObject().c_str());
167 // Verify that the information in Attach is correct.
168 BrowserPluginHostMsg_Attach_Params params;
169 MockBrowserPlugin* browser_plugin = GetCurrentPluginWithAttachParams(&params);
171 EXPECT_EQ(640, params.resize_guest_params.view_size.width());
172 EXPECT_EQ(480, params.resize_guest_params.view_size.height());
173 ASSERT_TRUE(browser_plugin);
176 TEST_F(BrowserPluginTest, ResizeFlowControl) {
177 LoadHTML(GetHTMLForBrowserPluginObject().c_str());
178 MockBrowserPlugin* browser_plugin = GetCurrentPlugin();
179 ASSERT_TRUE(browser_plugin);
180 int instance_id = browser_plugin->browser_plugin_instance_id();
181 // Send an UpdateRect to the BrowserPlugin to make sure the browser sees a
182 // resize related (SetAutoSize) message.
184 // We send a stale UpdateRect to the BrowserPlugin.
185 BrowserPluginMsg_UpdateRect_Params update_rect_params;
186 update_rect_params.view_size = gfx::Size(640, 480);
187 update_rect_params.scale_factor = 1.0f;
188 update_rect_params.is_resize_ack = true;
189 BrowserPluginMsg_UpdateRect msg(instance_id, update_rect_params);
190 browser_plugin->OnMessageReceived(msg);
193 browser_plugin_manager()->sink().ClearMessages();
195 // Resize the browser plugin three times.
197 ExecuteJavaScript("document.getElementById('browserplugin').width = '641px'");
198 GetMainFrame()->view()->layout();
199 ProcessPendingMessages();
201 ExecuteJavaScript("document.getElementById('browserplugin').width = '642px'");
202 GetMainFrame()->view()->layout();
203 ProcessPendingMessages();
205 ExecuteJavaScript("document.getElementById('browserplugin').width = '643px'");
206 GetMainFrame()->view()->layout();
207 ProcessPendingMessages();
209 // Expect to see one resize messsage in the sink. BrowserPlugin will not issue
210 // subsequent resize requests until the first request is satisfied by the
211 // guest. The rest of the messages could be
212 // BrowserPluginHostMsg_UpdateGeometry msgs.
213 EXPECT_LE(1u, browser_plugin_manager()->sink().message_count());
214 for (size_t i = 0; i < browser_plugin_manager()->sink().message_count();
215 ++i) {
216 const IPC::Message* msg = browser_plugin_manager()->sink().GetMessageAt(i);
217 if (msg->type() != BrowserPluginHostMsg_ResizeGuest::ID)
218 EXPECT_EQ(msg->type(), BrowserPluginHostMsg_UpdateGeometry::ID);
220 const IPC::Message* msg =
221 browser_plugin_manager()->sink().GetUniqueMessageMatching(
222 BrowserPluginHostMsg_ResizeGuest::ID);
223 ASSERT_TRUE(msg);
224 BrowserPluginHostMsg_ResizeGuest::Param param;
225 BrowserPluginHostMsg_ResizeGuest::Read(msg, &param);
226 instance_id = param.a;
227 BrowserPluginHostMsg_ResizeGuest_Params params = param.b;
228 EXPECT_EQ(641, params.view_size.width());
229 EXPECT_EQ(480, params.view_size.height());
232 // We send a stale UpdateRect to the BrowserPlugin.
233 BrowserPluginMsg_UpdateRect_Params update_rect_params;
234 update_rect_params.view_size = gfx::Size(641, 480);
235 update_rect_params.scale_factor = 1.0f;
236 update_rect_params.is_resize_ack = true;
237 BrowserPluginMsg_UpdateRect msg(instance_id, update_rect_params);
238 browser_plugin->OnMessageReceived(msg);
240 // Send the BrowserPlugin another UpdateRect, but this time with a size
241 // that matches the size of the container.
243 BrowserPluginMsg_UpdateRect_Params update_rect_params;
244 update_rect_params.view_size = gfx::Size(643, 480);
245 update_rect_params.scale_factor = 1.0f;
246 update_rect_params.is_resize_ack = true;
247 BrowserPluginMsg_UpdateRect msg(instance_id, update_rect_params);
248 browser_plugin->OnMessageReceived(msg);
252 TEST_F(BrowserPluginTest, RemovePlugin) {
253 LoadHTML(GetHTMLForBrowserPluginObject().c_str());
254 MockBrowserPlugin* browser_plugin = GetCurrentPlugin();
255 ASSERT_TRUE(browser_plugin);
257 EXPECT_FALSE(browser_plugin_manager()->sink().GetUniqueMessageMatching(
258 BrowserPluginHostMsg_PluginDestroyed::ID));
259 ExecuteJavaScript("x = document.getElementById('browserplugin'); "
260 "x.parentNode.removeChild(x);");
261 ProcessPendingMessages();
262 EXPECT_TRUE(browser_plugin_manager()->sink().GetUniqueMessageMatching(
263 BrowserPluginHostMsg_PluginDestroyed::ID));
266 // This test verifies that PluginDestroyed messages do not get sent from a
267 // BrowserPlugin that has never navigated.
268 TEST_F(BrowserPluginTest, RemovePluginBeforeNavigation) {
269 std::string html = base::StringPrintf(kHTMLForSourcelessPluginObject,
270 kBrowserPluginMimeType);
271 LoadHTML(html.c_str());
272 EXPECT_FALSE(browser_plugin_manager()->sink().GetUniqueMessageMatching(
273 BrowserPluginHostMsg_PluginDestroyed::ID));
274 ExecuteJavaScript("x = document.getElementById('browserplugin'); "
275 "x.parentNode.removeChild(x);");
276 ProcessPendingMessages();
277 EXPECT_FALSE(browser_plugin_manager()->sink().GetUniqueMessageMatching(
278 BrowserPluginHostMsg_PluginDestroyed::ID));
281 } // namespace content