Home | History | Annotate | Download | only in pepper
      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 "base/basictypes.h"
      6 #include "base/memory/scoped_ptr.h"
      7 #include "content/renderer/pepper/host_globals.h"
      8 #include "content/renderer/pepper/host_var_tracker.h"
      9 #include "content/renderer/pepper/mock_resource.h"
     10 #include "content/renderer/pepper/pepper_plugin_instance_impl.h"
     11 #include "content/renderer/pepper/pepper_try_catch.h"
     12 #include "content/renderer/pepper/v8object_var.h"
     13 #include "content/test/ppapi_unittest.h"
     14 #include "gin/handle.h"
     15 #include "gin/wrappable.h"
     16 #include "ppapi/c/pp_var.h"
     17 #include "ppapi/c/ppp_instance.h"
     18 #include "third_party/WebKit/public/web/WebBindings.h"
     19 
     20 using ppapi::V8ObjectVar;
     21 
     22 namespace content {
     23 
     24 namespace {
     25 
     26 int g_v8objects_alive = 0;
     27 
     28 class MyObject : public gin::Wrappable<MyObject> {
     29  public:
     30   static gin::WrapperInfo kWrapperInfo;
     31 
     32   static v8::Handle<v8::Value> Create(v8::Isolate* isolate) {
     33     return gin::CreateHandle(isolate, new MyObject()).ToV8();
     34   }
     35 
     36  private:
     37   MyObject() { ++g_v8objects_alive; }
     38   virtual ~MyObject() { --g_v8objects_alive; }
     39 
     40   DISALLOW_COPY_AND_ASSIGN(MyObject);
     41 };
     42 
     43 gin::WrapperInfo MyObject::kWrapperInfo = {gin::kEmbedderNativeGin};
     44 
     45 class PepperTryCatchForTest : public PepperTryCatch {
     46  public:
     47   explicit PepperTryCatchForTest(PepperPluginInstanceImpl* instance)
     48       : PepperTryCatch(instance, V8VarConverter::kAllowObjectVars),
     49         handle_scope_(instance->GetIsolate()),
     50         context_scope_(v8::Context::New(instance->GetIsolate())) {}
     51 
     52   virtual void SetException(const char* message) OVERRIDE { NOTREACHED(); }
     53   virtual bool HasException() OVERRIDE { return false; }
     54   virtual v8::Handle<v8::Context> GetContext() OVERRIDE {
     55     return instance_->GetIsolate()->GetCurrentContext();
     56   }
     57 
     58  private:
     59   v8::HandleScope handle_scope_;
     60   v8::Context::Scope context_scope_;
     61 
     62   DISALLOW_COPY_AND_ASSIGN(PepperTryCatchForTest);
     63 };
     64 
     65 }  // namespace
     66 
     67 class HostVarTrackerTest : public PpapiUnittest {
     68  public:
     69   HostVarTrackerTest() {}
     70 
     71   virtual void TearDown() OVERRIDE {
     72     v8::Isolate::GetCurrent()->RequestGarbageCollectionForTesting(
     73         v8::Isolate::kFullGarbageCollection);
     74     EXPECT_EQ(0, g_v8objects_alive);
     75     PpapiUnittest::TearDown();
     76   }
     77 
     78   HostVarTracker& tracker() { return *HostGlobals::Get()->host_var_tracker(); }
     79 };
     80 
     81 TEST_F(HostVarTrackerTest, DeleteObjectVarWithInstance) {
     82   v8::Isolate* test_isolate = v8::Isolate::GetCurrent();
     83 
     84   // Make a second instance (the test harness already creates & manages one).
     85   scoped_refptr<PepperPluginInstanceImpl> instance2(
     86       PepperPluginInstanceImpl::Create(NULL, module(), NULL, GURL()));
     87   PP_Instance pp_instance2 = instance2->pp_instance();
     88 
     89   {
     90     PepperTryCatchForTest try_catch(instance2.get());
     91     // Make an object var.
     92     ppapi::ScopedPPVar var = try_catch.FromV8(MyObject::Create(test_isolate));
     93     EXPECT_EQ(1, g_v8objects_alive);
     94     EXPECT_EQ(1, tracker().GetLiveV8ObjectVarsForTest(pp_instance2));
     95     // Purposely leak the var.
     96     var.Release();
     97   }
     98 
     99   // Free the instance, this should release the ObjectVar.
    100   instance2 = NULL;
    101   EXPECT_EQ(0, tracker().GetLiveV8ObjectVarsForTest(pp_instance2));
    102 }
    103 
    104 // Make sure that using the same v8 object should give the same PP_Var
    105 // each time.
    106 TEST_F(HostVarTrackerTest, ReuseVar) {
    107   PepperTryCatchForTest try_catch(instance());
    108 
    109   v8::Handle<v8::Value> v8_object = MyObject::Create(v8::Isolate::GetCurrent());
    110   ppapi::ScopedPPVar pp_object1 = try_catch.FromV8(v8_object);
    111   ppapi::ScopedPPVar pp_object2 = try_catch.FromV8(v8_object);
    112 
    113   // The two results should be the same.
    114   EXPECT_EQ(pp_object1.get().value.as_id, pp_object2.get().value.as_id);
    115 
    116   // The objects should be able to get us back to the associated v8 object.
    117   {
    118     scoped_refptr<V8ObjectVar> check_object(
    119         V8ObjectVar::FromPPVar(pp_object1.get()));
    120     ASSERT_TRUE(check_object.get());
    121     EXPECT_EQ(instance(), check_object->instance());
    122     EXPECT_EQ(v8_object, check_object->GetHandle());
    123   }
    124 
    125   // Remove both of the refs we made above.
    126   pp_object1 = ppapi::ScopedPPVar();
    127   pp_object2 = ppapi::ScopedPPVar();
    128 
    129   // Releasing the resource should free the internal ref, and so making a new
    130   // one now should generate a new ID.
    131   ppapi::ScopedPPVar pp_object3 = try_catch.FromV8(v8_object);
    132   EXPECT_NE(pp_object1.get().value.as_id, pp_object3.get().value.as_id);
    133 }
    134 
    135 }  // namespace content
    136