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"
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);
44 // Test factory for creating test instances of BrowserPluginManager.
45 class TestBrowserPluginManagerFactory : public BrowserPluginManagerFactory {
47 virtual MockBrowserPluginManager* CreateBrowserPluginManager(
48 RenderViewImpl* render_view) OVERRIDE {
49 return new MockBrowserPluginManager(render_view);
53 static TestBrowserPluginManagerFactory* GetInstance() {
54 return Singleton<TestBrowserPluginManagerFactory>::get();
58 TestBrowserPluginManagerFactory() {}
59 virtual ~TestBrowserPluginManagerFactory() {}
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();
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())
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);
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())
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())
125 *result = value->BooleanValue();
129 MockBrowserPlugin* BrowserPluginTest::GetCurrentPlugin() {
130 BrowserPluginHostMsg_Attach_Params params;
131 return GetCurrentPluginWithAttachParams(¶ms);
134 MockBrowserPlugin* BrowserPluginTest::GetCurrentPluginWithAttachParams(
135 BrowserPluginHostMsg_Attach_Params* params) {
136 MockBrowserPlugin* browser_plugin = static_cast<MockBrowserPluginManager*>(
137 browser_plugin_manager())->last_plugin();
141 browser_plugin->Attach();
144 const IPC::Message* msg =
145 browser_plugin_manager()->sink().GetUniqueMessageMatching(
146 BrowserPluginHostMsg_Attach::ID);
150 PickleIterator iter(*msg);
151 if (!iter.ReadInt(&instance_id))
154 if (!IPC::ParamTraits<BrowserPluginHostMsg_Attach_Params>::Read(
155 msg, &iter, params)) {
159 browser_plugin->OnAttachACK(instance_id);
160 return browser_plugin;
163 // This test verifies that an initial resize occurs when we instantiate the
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(¶ms);
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, RemovePlugin) {
177 LoadHTML(GetHTMLForBrowserPluginObject().c_str());
178 MockBrowserPlugin* browser_plugin = GetCurrentPlugin();
179 ASSERT_TRUE(browser_plugin);
181 EXPECT_FALSE(browser_plugin_manager()->sink().GetUniqueMessageMatching(
182 BrowserPluginHostMsg_PluginDestroyed::ID));
183 ExecuteJavaScript("x = document.getElementById('browserplugin'); "
184 "x.parentNode.removeChild(x);");
185 ProcessPendingMessages();
186 EXPECT_TRUE(browser_plugin_manager()->sink().GetUniqueMessageMatching(
187 BrowserPluginHostMsg_PluginDestroyed::ID));
190 // This test verifies that PluginDestroyed messages do not get sent from a
191 // BrowserPlugin that has never navigated.
192 TEST_F(BrowserPluginTest, RemovePluginBeforeNavigation) {
193 std::string html = base::StringPrintf(kHTMLForSourcelessPluginObject,
194 kBrowserPluginMimeType);
195 LoadHTML(html.c_str());
196 EXPECT_FALSE(browser_plugin_manager()->sink().GetUniqueMessageMatching(
197 BrowserPluginHostMsg_PluginDestroyed::ID));
198 ExecuteJavaScript("x = document.getElementById('browserplugin'); "
199 "x.parentNode.removeChild(x);");
200 ProcessPendingMessages();
201 EXPECT_FALSE(browser_plugin_manager()->sink().GetUniqueMessageMatching(
202 BrowserPluginHostMsg_PluginDestroyed::ID));
205 } // namespace content