Home | History | Annotate | Download | only in browser_plugin
      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/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"
     25 
     26 namespace content {
     27 
     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>";
     33 
     34 const char kHTMLForSourcelessPluginObject[] =
     35     "<object id='browserplugin' width='640px' height='480px' type='%s'>";
     36 
     37 std::string GetHTMLForBrowserPluginObject() {
     38   return base::StringPrintf(kHTMLForBrowserPluginObject,
     39                             kBrowserPluginMimeType);
     40 }
     41 
     42 }  // namespace
     43 
     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);
     50   }
     51 
     52   // Singleton getter.
     53   static TestBrowserPluginManagerFactory* GetInstance() {
     54     return Singleton<TestBrowserPluginManagerFactory>::get();
     55   }
     56 
     57  protected:
     58   TestBrowserPluginManagerFactory() {}
     59   virtual ~TestBrowserPluginManagerFactory() {}
     60 
     61  private:
     62   // For Singleton.
     63   friend struct DefaultSingletonTraits<TestBrowserPluginManagerFactory>;
     64 
     65   DISALLOW_COPY_AND_ASSIGN(TestBrowserPluginManagerFactory);
     66 };
     67 
     68 BrowserPluginTest::BrowserPluginTest() {}
     69 
     70 BrowserPluginTest::~BrowserPluginTest() {}
     71 
     72 void BrowserPluginTest::SetUp() {
     73   BrowserPluginManager::set_factory_for_testing(
     74       TestBrowserPluginManagerFactory::GetInstance());
     75   content::RenderViewTest::SetUp();
     76 }
     77 
     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();
     87 }
     88 
     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();
     96 
     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();
    102 }
    103 
    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;
    111 
    112   return value->Int32Value();
    113 }
    114 
    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;
    124 
    125   *result = value->BooleanValue();
    126   return true;
    127 }
    128 
    129 MockBrowserPlugin* BrowserPluginTest::GetCurrentPlugin() {
    130   BrowserPluginHostMsg_Attach_Params params;
    131   return GetCurrentPluginWithAttachParams(&params);
    132 }
    133 
    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;
    140 
    141   browser_plugin->Attach();
    142 
    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;
    149 
    150   PickleIterator iter(*msg);
    151   if (!iter.ReadInt(&instance_id))
    152     return NULL;
    153 
    154   if (!IPC::ParamTraits<BrowserPluginHostMsg_Attach_Params>::Read(
    155       msg, &iter, params)) {
    156     return NULL;
    157   }
    158 
    159   browser_plugin->OnAttachACK(instance_id);
    160   return browser_plugin;
    161 }
    162 
    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);
    170 
    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);
    174 }
    175 
    176 TEST_F(BrowserPluginTest, RemovePlugin) {
    177   LoadHTML(GetHTMLForBrowserPluginObject().c_str());
    178   MockBrowserPlugin* browser_plugin = GetCurrentPlugin();
    179   ASSERT_TRUE(browser_plugin);
    180 
    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));
    188 }
    189 
    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));
    203 }
    204 
    205 }  // namespace content
    206