OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "content/renderer/browser_plugin/browser_plugin_browsertest.h" | |
6 | |
7 #include "base/file_path.h" | |
8 #include "base/file_util.h" | |
9 #include "base/path_service.h" | |
10 #include "content/common/browser_plugin_messages.h" | |
11 #include "content/public/common/content_constants.h" | |
12 #include "content/renderer/browser_plugin/browser_plugin.h" | |
13 #include "content/renderer/browser_plugin/mock_browser_plugin.h" | |
14 #include "content/renderer/browser_plugin/mock_browser_plugin_manager.h" | |
15 #include "content/renderer/render_thread_impl.h" | |
16 #include "content/renderer/renderer_webkitplatformsupport_impl.h" | |
17 #include "skia/ext/platform_canvas.h" | |
18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h" | |
19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" | |
20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebScriptSource.h" | |
21 | |
22 namespace { | |
23 const char kHTMLForBrowserPluginObject[] = | |
24 "<object id='browserplugin' width='640px' height='480px'" | |
25 " src='foo' type='%s'>"; | |
26 | |
27 std::string GetHTMLForBrowserPluginObject() { | |
28 return StringPrintf(kHTMLForBrowserPluginObject, | |
29 content::kBrowserPluginNewMimeType); | |
30 } | |
31 | |
32 } | |
33 | |
34 namespace content { | |
35 | |
36 BrowserPluginTest::BrowserPluginTest() {} | |
37 | |
38 BrowserPluginTest::~BrowserPluginTest() {} | |
39 | |
40 void BrowserPluginTest::SetUp() { | |
41 GetContentClient()->set_renderer_for_testing(&content_renderer_client_); | |
42 content::RenderViewTest::SetUp(); | |
43 browser_plugin_manager_.reset(new MockBrowserPluginManager()); | |
44 } | |
45 | |
46 void BrowserPluginTest::TearDown() { | |
47 browser_plugin_manager_->Cleanup(); | |
48 content::RenderViewTest::TearDown(); | |
49 } | |
50 | |
51 std::string BrowserPluginTest::ExecuteScriptAndReturnString( | |
52 const std::string& script) { | |
53 v8::Handle<v8::Value> value = GetMainFrame()->executeScriptAndReturnValue( | |
54 WebKit::WebScriptSource(WebKit::WebString::fromUTF8(script.c_str()))); | |
55 if (value.IsEmpty() || !value->IsString()) | |
56 return std::string(); | |
57 | |
58 v8::Local<v8::String> v8_str = value->ToString(); | |
59 int length = v8_str->Utf8Length() + 1; | |
60 scoped_array<char> str(new char[length]); | |
61 v8_str->WriteUtf8(str.get(), length); | |
62 return str.get(); | |
63 } | |
64 | |
65 // This test verifies that an initial resize occurs when we instantiate the | |
66 // browser plugin. This test also verifies that the browser plugin is waiting | |
67 // for a BrowserPluginMsg_UpdateRect in response. We issue an UpdateRect, and | |
68 // we observe an UpdateRect_ACK, with the resize_pending_ reset, indiciating | |
69 // that the BrowserPlugin is not waiting for any more UpdateRects to | |
70 // satisfy its resize request. | |
71 TEST_F(BrowserPluginTest, InitialResize) { | |
72 LoadHTML(GetHTMLForBrowserPluginObject().c_str()); | |
73 // Verify that the information based on ResizeGuest is correct, and | |
74 // use its TransportDIB::Id to paint. | |
75 const IPC::Message* msg = | |
76 browser_plugin_manager()->sink().GetUniqueMessageMatching( | |
77 BrowserPluginHostMsg_ResizeGuest::ID); | |
78 ASSERT_TRUE(msg); | |
79 PickleIterator iter = IPC::SyncMessage::GetDataIterator(msg); | |
80 BrowserPluginHostMsg_ResizeGuest::SendParam resize_params; | |
81 ASSERT_TRUE(IPC::ReadParam(msg, &iter, &resize_params)); | |
82 int instance_id = resize_params.a; | |
83 BrowserPluginHostMsg_ResizeGuest_Params params(resize_params.b); | |
84 EXPECT_EQ(640, params.width); | |
85 EXPECT_EQ(480, params.height); | |
86 // Verify that the browser plugin wasn't already waiting on a resize when this | |
87 // resize happened. | |
88 EXPECT_EQ(false, params.resize_pending); | |
89 | |
90 MockBrowserPlugin* browser_plugin = | |
91 static_cast<MockBrowserPlugin*>( | |
92 browser_plugin_manager()->GetBrowserPlugin(instance_id)); | |
93 ASSERT_TRUE(browser_plugin); | |
94 // Now the browser plugin is expecting a UpdateRect resize. | |
95 EXPECT_TRUE(browser_plugin->resize_pending_); | |
96 | |
97 // Send the BrowserPlugin an UpdateRect equal to its container size. | |
98 // That should clear the resize_pending_ flag. | |
99 BrowserPluginMsg_UpdateRect_Params update_rect_params; | |
100 update_rect_params.view_size = gfx::Size(640, 480); | |
101 update_rect_params.scale_factor = 1.0f; | |
102 update_rect_params.is_resize_ack = true; | |
103 browser_plugin->UpdateRect(0, update_rect_params); | |
104 EXPECT_FALSE(browser_plugin->resize_pending_); | |
105 } | |
106 | |
107 // Verify that the src attribute on the browser plugin works as expected. | |
108 TEST_F(BrowserPluginTest, SrcAttribute) { | |
109 LoadHTML(GetHTMLForBrowserPluginObject().c_str()); | |
110 // Verify that we're reporting the correct URL to navigate to based on the | |
111 // src attribute. | |
112 { | |
113 const IPC::Message* msg = | |
114 browser_plugin_manager()->sink().GetUniqueMessageMatching( | |
115 BrowserPluginHostMsg_NavigateOrCreateGuest::ID); | |
116 ASSERT_TRUE(msg); | |
117 | |
118 int instance_id; | |
119 long long frame_id; | |
120 std::string src; | |
121 BrowserPluginHostMsg_NavigateOrCreateGuest::Read( | |
122 msg, | |
123 &instance_id, | |
124 &frame_id, | |
125 &src); | |
126 EXPECT_EQ("foo", src); | |
127 } | |
128 | |
129 browser_plugin_manager()->sink().ClearMessages(); | |
130 // Navigate to bar and observe the associated | |
131 // BrowserPluginHostMsg_NavigateOrCreateGuest message. | |
132 // Verify that the src attribute is updated as well. | |
133 ExecuteJavaScript("document.getElementById('browserplugin').src = 'bar'"); | |
134 { | |
135 const IPC::Message* msg = | |
136 browser_plugin_manager()->sink().GetUniqueMessageMatching( | |
137 BrowserPluginHostMsg_NavigateOrCreateGuest::ID); | |
138 ASSERT_TRUE(msg); | |
139 | |
140 int instance_id; | |
141 long long frame_id; | |
142 std::string src; | |
143 BrowserPluginHostMsg_NavigateOrCreateGuest::Read( | |
144 msg, | |
145 &instance_id, | |
146 &frame_id, | |
147 &src); | |
148 EXPECT_EQ("bar", src); | |
149 std::string src_value = | |
150 ExecuteScriptAndReturnString( | |
151 "document.getElementById('browserplugin').src"); | |
152 EXPECT_EQ("bar", src_value); | |
153 } | |
154 } | |
155 | |
156 TEST_F(BrowserPluginTest, ResizeFlowControl) { | |
157 LoadHTML(GetHTMLForBrowserPluginObject().c_str()); | |
158 browser_plugin_manager()->sink().ClearMessages(); | |
159 | |
160 // Resize the browser plugin three times. | |
161 ExecuteJavaScript("document.getElementById('browserplugin').width = '641px'"); | |
162 ProcessPendingMessages(); | |
163 ExecuteJavaScript("document.getElementById('browserplugin').width = '642px'"); | |
164 ProcessPendingMessages(); | |
165 ExecuteJavaScript("document.getElementById('browserplugin').width = '643px'"); | |
166 ProcessPendingMessages(); | |
167 | |
168 // Expect to see three messsages in the sink. | |
169 EXPECT_EQ(3u, browser_plugin_manager()->sink().message_count()); | |
170 const IPC::Message* msg = | |
171 browser_plugin_manager()->sink().GetFirstMessageMatching( | |
172 BrowserPluginHostMsg_ResizeGuest::ID); | |
173 ASSERT_TRUE(msg); | |
174 PickleIterator iter = IPC::SyncMessage::GetDataIterator(msg); | |
175 BrowserPluginHostMsg_ResizeGuest::SendParam resize_params; | |
176 ASSERT_TRUE(IPC::ReadParam(msg, &iter, &resize_params)); | |
177 int instance_id = resize_params.a; | |
178 BrowserPluginHostMsg_ResizeGuest_Params params(resize_params.b); | |
179 EXPECT_EQ(641, params.width); | |
180 EXPECT_EQ(480, params.height); | |
181 // This indicates that the BrowserPlugin has sent out a previous resize | |
182 // request but has not yet received an UpdateRect for that request. | |
183 // We send this resize regardless to update the damage buffer in the | |
184 // browser process, so it's ready when the guest sends the appropriate | |
185 // UpdateRect. | |
186 EXPECT_TRUE(params.resize_pending); | |
187 | |
188 MockBrowserPlugin* browser_plugin = | |
189 static_cast<MockBrowserPlugin*>( | |
190 browser_plugin_manager()->GetBrowserPlugin(instance_id)); | |
191 ASSERT_TRUE(browser_plugin); | |
192 { | |
193 // We send a stale UpdateRect to the BrowserPlugin. | |
194 BrowserPluginMsg_UpdateRect_Params update_rect_params; | |
195 update_rect_params.view_size = gfx::Size(640, 480); | |
196 update_rect_params.scale_factor = 1.0f; | |
197 update_rect_params.is_resize_ack = true; | |
198 browser_plugin->UpdateRect(0, update_rect_params); | |
199 // This tells us that the BrowserPlugin is still expecting another | |
200 // UpdateRect with the most recent size. | |
201 EXPECT_TRUE(browser_plugin->resize_pending_); | |
202 } | |
203 { | |
204 BrowserPluginMsg_UpdateRect_Params update_rect_params; | |
205 update_rect_params.view_size = gfx::Size(643, 480); | |
206 update_rect_params.scale_factor = 1.0f; | |
207 update_rect_params.is_resize_ack = true; | |
208 browser_plugin->UpdateRect(0, update_rect_params); | |
209 // The BrowserPlugin has finally received an UpdateRect that satisifes | |
210 // its current size, and so it is happy. | |
211 EXPECT_FALSE(browser_plugin->resize_pending_); | |
212 } | |
213 } | |
214 | |
215 TEST_F(BrowserPluginTest, GuestCrash) { | |
216 LoadHTML(GetHTMLForBrowserPluginObject().c_str()); | |
217 | |
218 // Grab the BrowserPlugin's instance ID from its resize message. | |
219 const IPC::Message* msg = | |
220 browser_plugin_manager()->sink().GetFirstMessageMatching( | |
221 BrowserPluginHostMsg_ResizeGuest::ID); | |
222 ASSERT_TRUE(msg); | |
223 PickleIterator iter = IPC::SyncMessage::GetDataIterator(msg); | |
224 BrowserPluginHostMsg_ResizeGuest::SendParam resize_params; | |
225 ASSERT_TRUE(IPC::ReadParam(msg, &iter, &resize_params)); | |
226 int instance_id = resize_params.a; | |
227 | |
228 MockBrowserPlugin* browser_plugin = | |
229 static_cast<MockBrowserPlugin*>( | |
230 browser_plugin_manager()->GetBrowserPlugin(instance_id)); | |
231 ASSERT_TRUE(browser_plugin); | |
232 | |
233 WebKit::WebCursorInfo cursor_info; | |
234 // Send an event and verify that the event is deported. | |
235 browser_plugin->handleInputEvent(WebKit::WebMouseEvent(), | |
236 cursor_info); | |
237 EXPECT_TRUE(browser_plugin_manager()->sink().GetUniqueMessageMatching( | |
238 BrowserPluginHostMsg_HandleInputEvent::ID)); | |
239 browser_plugin_manager()->sink().ClearMessages(); | |
240 | |
241 // Pretend that the guest has crashed | |
242 browser_plugin->GuestCrashed(); | |
243 // Send an event and verify that events are no longer deported. | |
244 browser_plugin->handleInputEvent(WebKit::WebMouseEvent(), | |
245 cursor_info); | |
246 EXPECT_FALSE(browser_plugin_manager()->sink().GetUniqueMessageMatching( | |
247 BrowserPluginHostMsg_HandleInputEvent::ID)); | |
248 | |
249 // Navigate and verify that the guest_crashed_ flag has been reset. | |
250 browser_plugin->SetSrcAttribute("bar"); | |
251 EXPECT_FALSE(browser_plugin->guest_crashed_); | |
252 | |
253 } | |
254 | |
255 TEST_F(BrowserPluginTest, RemovePlugin) { | |
256 LoadHTML(GetHTMLForBrowserPluginObject().c_str()); | |
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)); | |
264 } | |
265 | |
266 TEST_F(BrowserPluginTest, CustomEvents) { | |
267 const char* kAddEventListener = | |
268 "var url;" | |
269 "function nav(u) {" | |
270 " url = u;" | |
271 "}" | |
272 "document.getElementById('browserplugin')." | |
273 " addEventListener('navigation', nav);"; | |
274 const char* kRemoveEventListener = | |
275 "document.getElementById('browserplugin')." | |
276 " removeEventListener('navigation', nav);"; | |
277 const char* kGoogleURL = "http://www.google.com/"; | |
278 const char* kGoogleNewsURL = "http://news.google.com/"; | |
279 | |
280 LoadHTML(GetHTMLForBrowserPluginObject().c_str()); | |
281 ExecuteJavaScript(kAddEventListener); | |
282 // Grab the BrowserPlugin's instance ID from its resize message. | |
283 const IPC::Message* msg = | |
284 browser_plugin_manager()->sink().GetFirstMessageMatching( | |
285 BrowserPluginHostMsg_ResizeGuest::ID); | |
286 ASSERT_TRUE(msg); | |
287 PickleIterator iter = IPC::SyncMessage::GetDataIterator(msg); | |
288 BrowserPluginHostMsg_ResizeGuest::SendParam resize_params; | |
289 ASSERT_TRUE(IPC::ReadParam(msg, &iter, &resize_params)); | |
290 int instance_id = resize_params.a; | |
291 | |
292 MockBrowserPlugin* browser_plugin = | |
293 static_cast<MockBrowserPlugin*>( | |
294 browser_plugin_manager()->GetBrowserPlugin(instance_id)); | |
295 ASSERT_TRUE(browser_plugin); | |
296 | |
297 browser_plugin->DidNavigate(GURL(kGoogleURL)); | |
298 EXPECT_EQ(kGoogleURL, ExecuteScriptAndReturnString("url")); | |
299 | |
300 ExecuteJavaScript(kRemoveEventListener); | |
301 browser_plugin->DidNavigate(GURL(kGoogleNewsURL)); | |
302 // The URL variable should not change because we've removed the event | |
303 // listener. | |
304 EXPECT_EQ(kGoogleURL, ExecuteScriptAndReturnString("url")); | |
305 } | |
306 | |
307 } // namespace content | |
OLD | NEW |