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 |