Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/basictypes.h" | |
| 5 #include "base/memory/scoped_ptr.h" | 6 #include "base/memory/scoped_ptr.h" |
| 6 #include "content/renderer/pepper/host_globals.h" | 7 #include "content/renderer/pepper/host_globals.h" |
| 7 #include "content/renderer/pepper/host_var_tracker.h" | 8 #include "content/renderer/pepper/host_var_tracker.h" |
| 8 #include "content/renderer/pepper/mock_resource.h" | 9 #include "content/renderer/pepper/mock_resource.h" |
| 9 #include "content/renderer/pepper/npapi_glue.h" | |
| 10 #include "content/renderer/pepper/npobject_var.h" | |
| 11 #include "content/renderer/pepper/pepper_plugin_instance_impl.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" | |
| 12 #include "content/test/ppapi_unittest.h" | 13 #include "content/test/ppapi_unittest.h" |
| 14 #include "gin/handle.h" | |
| 15 #include "gin/wrappable.h" | |
| 13 #include "ppapi/c/pp_var.h" | 16 #include "ppapi/c/pp_var.h" |
| 14 #include "ppapi/c/ppp_instance.h" | 17 #include "ppapi/c/ppp_instance.h" |
| 15 #include "third_party/npapi/bindings/npruntime.h" | |
| 16 #include "third_party/WebKit/public/web/WebBindings.h" | 18 #include "third_party/WebKit/public/web/WebBindings.h" |
| 17 | 19 |
| 18 using ppapi::NPObjectVar; | 20 using ppapi::V8ObjectVar; |
| 19 | 21 |
| 20 namespace content { | 22 namespace content { |
| 21 | 23 |
| 22 namespace { | 24 namespace { |
| 23 | 25 |
| 24 // Tracked NPObjects ----------------------------------------------------------- | 26 int g_v8objects_alive = 0; |
| 25 | 27 |
| 26 int g_npobjects_alive = 0; | 28 class MyObject : public gin::Wrappable<MyObject> { |
| 29 public: | |
| 30 static gin::WrapperInfo kWrapperInfo; | |
| 27 | 31 |
| 28 void TrackedClassDeallocate(NPObject* npobject) { | 32 static v8::Handle<v8::Value> Create(v8::Isolate* isolate) { |
| 29 g_npobjects_alive--; | 33 return gin::CreateHandle(isolate, new MyObject()).ToV8(); |
| 30 delete npobject; | 34 } |
| 31 } | |
| 32 | 35 |
| 33 NPClass g_tracked_npclass = { | 36 private: |
| 34 NP_CLASS_STRUCT_VERSION, NULL, &TrackedClassDeallocate, NULL, NULL, NULL, | 37 MyObject() { ++g_v8objects_alive; } |
| 35 NULL, NULL, NULL, NULL, NULL, NULL, }; | 38 virtual ~MyObject() { --g_v8objects_alive; } |
| 36 | 39 |
| 37 // Returns a new tracked NPObject with a refcount of 1. You'll want to put this | 40 DISALLOW_COPY_AND_ASSIGN(MyObject); |
| 38 // in a NPObjectReleaser to free this ref when the test completes. | |
| 39 NPObject* NewTrackedNPObject() { | |
| 40 NPObject* object = new NPObject; | |
| 41 object->_class = &g_tracked_npclass; | |
| 42 object->referenceCount = 1; | |
| 43 | |
| 44 g_npobjects_alive++; | |
| 45 return object; | |
| 46 } | |
| 47 | |
| 48 struct ReleaseNPObject { | |
| 49 void operator()(NPObject* o) const { blink::WebBindings::releaseObject(o); } | |
| 50 }; | 41 }; |
| 51 | 42 |
| 52 // Handles automatically releasing a reference to the NPObject on destruction. | 43 gin::WrapperInfo MyObject::kWrapperInfo = {gin::kEmbedderNativeGin}; |
| 53 // It's assumed the input has a ref already taken. | 44 |
| 54 typedef scoped_ptr<NPObject, ReleaseNPObject> NPObjectReleaser; | 45 class PepperTryCatchForTest : public PepperTryCatch { |
| 46 public: | |
| 47 explicit PepperTryCatchForTest(PepperPluginInstanceImpl* instance) | |
| 48 : PepperTryCatch(instance, true), | |
| 49 handle_scope_(instance->GetIsolate()), | |
| 50 context_scope_(v8::Context::New(instance->GetIsolate())) {} | |
| 51 | |
| 52 virtual void SetException(const char* message) OVERRIDE { DCHECK(false); } | |
|
dmichael (off chromium)
2014/08/20 23:09:16
NOTREACHED()?
raymes
2014/08/22 08:28:40
Done.
| |
| 53 virtual v8::Handle<v8::Context> GetContext() OVERRIDE { | |
| 54 return instance_->GetIsolate()->GetCurrentContext(); | |
| 55 } | |
| 56 | |
| 57 private: | |
| 58 v8::HandleScope handle_scope_; | |
| 59 v8::Context::Scope context_scope_; | |
| 60 | |
| 61 DISALLOW_COPY_AND_ASSIGN(PepperTryCatchForTest); | |
| 62 }; | |
| 55 | 63 |
| 56 } // namespace | 64 } // namespace |
| 57 | 65 |
| 58 class HostVarTrackerTest : public PpapiUnittest { | 66 class HostVarTrackerTest : public PpapiUnittest { |
| 59 public: | 67 public: |
| 60 HostVarTrackerTest() {} | 68 HostVarTrackerTest() {} |
| 61 | 69 |
| 62 HostVarTracker& tracker() { return *HostGlobals::Get()->host_var_tracker(); } | 70 HostVarTracker& tracker() { return *HostGlobals::Get()->host_var_tracker(); } |
| 63 }; | 71 }; |
| 64 | 72 |
| 65 TEST_F(HostVarTrackerTest, DeleteObjectVarWithInstance) { | 73 TEST_F(HostVarTrackerTest, DeleteObjectVarWithInstance) { |
| 74 v8::Isolate* test_isolate = v8::Isolate::GetCurrent(); | |
| 75 | |
| 66 // Make a second instance (the test harness already creates & manages one). | 76 // Make a second instance (the test harness already creates & manages one). |
| 67 scoped_refptr<PepperPluginInstanceImpl> instance2( | 77 scoped_refptr<PepperPluginInstanceImpl> instance2( |
| 68 PepperPluginInstanceImpl::Create(NULL, module(), NULL, GURL())); | 78 PepperPluginInstanceImpl::Create(NULL, module(), NULL, GURL())); |
| 69 PP_Instance pp_instance2 = instance2->pp_instance(); | 79 PP_Instance pp_instance2 = instance2->pp_instance(); |
| 70 | 80 |
| 71 // Make an object var. | 81 { |
| 72 NPObjectReleaser npobject(NewTrackedNPObject()); | 82 PepperTryCatchForTest try_catch(instance2.get()); |
| 73 NPObjectToPPVarForTest(instance2.get(), npobject.get()); | 83 // Make an object var. |
| 74 | 84 ppapi::ScopedPPVar var = try_catch.FromV8(MyObject::Create(test_isolate)); |
| 75 EXPECT_EQ(1, g_npobjects_alive); | 85 EXPECT_EQ(1, g_v8objects_alive); |
| 76 EXPECT_EQ(1, tracker().GetLiveNPObjectVarsForInstance(pp_instance2)); | 86 EXPECT_EQ(1, tracker().GetLiveV8ObjectVarsForInstance(pp_instance2)); |
| 87 // Purposely leak the var. | |
| 88 var.Release(); | |
| 89 } | |
| 77 | 90 |
| 78 // Free the instance, this should release the ObjectVar. | 91 // Free the instance, this should release the ObjectVar. |
| 79 instance2 = NULL; | 92 instance2 = NULL; |
| 80 EXPECT_EQ(0, tracker().GetLiveNPObjectVarsForInstance(pp_instance2)); | 93 EXPECT_EQ(0, tracker().GetLiveV8ObjectVarsForInstance(pp_instance2)); |
| 94 test_isolate->RequestGarbageCollectionForTesting( | |
| 95 v8::Isolate::kFullGarbageCollection); | |
| 96 EXPECT_EQ(0, g_v8objects_alive); | |
| 81 } | 97 } |
| 82 | 98 |
| 83 // Make sure that using the same NPObject should give the same PP_Var | 99 // Make sure that using the same NPObject should give the same PP_Var |
| 84 // each time. | 100 // each time. |
| 85 TEST_F(HostVarTrackerTest, ReuseVar) { | 101 TEST_F(HostVarTrackerTest, ReuseVar) { |
| 86 NPObjectReleaser npobject(NewTrackedNPObject()); | 102 PepperTryCatchForTest try_catch(instance()); |
| 87 | 103 |
| 88 PP_Var pp_object1 = NPObjectToPPVarForTest(instance(), npobject.get()); | 104 v8::Handle<v8::Value> v8_object = MyObject::Create(v8::Isolate::GetCurrent()); |
| 89 PP_Var pp_object2 = NPObjectToPPVarForTest(instance(), npobject.get()); | 105 ppapi::ScopedPPVar pp_object1 = try_catch.FromV8(v8_object); |
| 106 ppapi::ScopedPPVar pp_object2 = try_catch.FromV8(v8_object); | |
| 90 | 107 |
| 91 // The two results should be the same. | 108 // The two results should be the same. |
| 92 EXPECT_EQ(pp_object1.value.as_id, pp_object2.value.as_id); | 109 EXPECT_EQ(pp_object1.get().value.as_id, pp_object2.get().value.as_id); |
| 93 | 110 |
| 94 // The objects should be able to get us back to the associated NPObject. | 111 // The objects should be able to get us back to the associated v8 object. |
| 95 // This ObjectVar must be released before we do NPObjectToPPVarForTest again | |
| 96 // below so it gets freed and we get a new identifier. | |
| 97 { | 112 { |
| 98 scoped_refptr<NPObjectVar> check_object(NPObjectVar::FromPPVar(pp_object1)); | 113 scoped_refptr<V8ObjectVar> check_object( |
| 114 V8ObjectVar::FromPPVar(pp_object1.get())); | |
| 99 ASSERT_TRUE(check_object.get()); | 115 ASSERT_TRUE(check_object.get()); |
| 100 EXPECT_EQ(instance()->pp_instance(), check_object->pp_instance()); | 116 EXPECT_EQ(instance(), check_object->instance()); |
| 101 EXPECT_EQ(npobject.get(), check_object->np_object()); | 117 EXPECT_EQ(v8_object, check_object->GetHandle()); |
| 102 } | 118 } |
| 103 | 119 |
| 104 // Remove both of the refs we made above. | 120 // Remove both of the refs we made above. |
| 105 ppapi::VarTracker* var_tracker = ppapi::PpapiGlobals::Get()->GetVarTracker(); | 121 pp_object1 = ppapi::ScopedPPVar(); |
| 106 var_tracker->ReleaseVar(static_cast<int32_t>(pp_object2.value.as_id)); | 122 pp_object2 = ppapi::ScopedPPVar(); |
| 107 var_tracker->ReleaseVar(static_cast<int32_t>(pp_object1.value.as_id)); | |
| 108 | 123 |
| 109 // Releasing the resource should free the internal ref, and so making a new | 124 // Releasing the resource should free the internal ref, and so making a new |
| 110 // one now should generate a new ID. | 125 // one now should generate a new ID. |
| 111 PP_Var pp_object3 = NPObjectToPPVarForTest(instance(), npobject.get()); | 126 ppapi::ScopedPPVar pp_object3 = try_catch.FromV8(v8_object); |
| 112 EXPECT_NE(pp_object1.value.as_id, pp_object3.value.as_id); | 127 EXPECT_NE(pp_object1.get().value.as_id, pp_object3.get().value.as_id); |
| 113 var_tracker->ReleaseVar(static_cast<int32_t>(pp_object3.value.as_id)); | |
| 114 } | 128 } |
| 115 | 129 |
| 116 } // namespace content | 130 } // namespace content |
| OLD | NEW |