summaryrefslogtreecommitdiffstats
path: root/chromium/content/renderer/pepper/host_var_tracker_unittest.cc
blob: 2c282161d7fb19cc836172ce328d9041d64a4be9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/renderer/pepper/host_var_tracker.h"

#include <memory>

#include "base/macros.h"
#include "content/renderer/pepper/host_globals.h"
#include "content/renderer/pepper/mock_resource.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
#include "content/renderer/pepper/pepper_try_catch.h"
#include "content/renderer/pepper/v8_var_converter.h"
#include "content/renderer/pepper/v8object_var.h"
#include "content/test/ppapi_unittest.h"
#include "gin/handle.h"
#include "gin/wrappable.h"
#include "ppapi/c/pp_var.h"
#include "ppapi/c/ppp_instance.h"

using ppapi::V8ObjectVar;

namespace content {

namespace {

int g_v8objects_alive = 0;

class MyObject : public gin::Wrappable<MyObject> {
 public:
  static gin::WrapperInfo kWrapperInfo;

  static v8::Local<v8::Value> Create(v8::Isolate* isolate) {
    return gin::CreateHandle(isolate, new MyObject()).ToV8();
  }

 private:
  MyObject() { ++g_v8objects_alive; }
  ~MyObject() override { --g_v8objects_alive; }

  DISALLOW_COPY_AND_ASSIGN(MyObject);
};

gin::WrapperInfo MyObject::kWrapperInfo = {gin::kEmbedderNativeGin};

class PepperTryCatchForTest : public PepperTryCatch {
 public:
  PepperTryCatchForTest(PepperPluginInstanceImpl* instance,
                        V8VarConverter* converter)
      : PepperTryCatch(instance, converter),
        handle_scope_(instance->GetIsolate()),
        context_scope_(v8::Context::New(instance->GetIsolate())) {}

  void SetException(const char* message) override { NOTREACHED(); }
  bool HasException() override { return false; }
  v8::Local<v8::Context> GetContext() override {
    return instance_->GetIsolate()->GetCurrentContext();
  }

 private:
  v8::HandleScope handle_scope_;
  v8::Context::Scope context_scope_;

  DISALLOW_COPY_AND_ASSIGN(PepperTryCatchForTest);
};

}  // namespace

class HostVarTrackerTest : public PpapiUnittest {
 public:
  HostVarTrackerTest() {}

  void TearDown() override {
    v8::Isolate::GetCurrent()->RequestGarbageCollectionForTesting(
        v8::Isolate::kFullGarbageCollection);
    EXPECT_EQ(0, g_v8objects_alive);
    PpapiUnittest::TearDown();
  }

  HostVarTracker& tracker() { return *HostGlobals::Get()->host_var_tracker(); }
};

TEST_F(HostVarTrackerTest, DeleteObjectVarWithInstance) {
  v8::Isolate* test_isolate = v8::Isolate::GetCurrent();

  // Make a second instance (the test harness already creates & manages one).
  scoped_refptr<PepperPluginInstanceImpl> instance2(
      PepperPluginInstanceImpl::Create(nullptr, module(), nullptr, GURL()));
  PP_Instance pp_instance2 = instance2->pp_instance();

  {
    V8VarConverter converter(
        instance2->pp_instance(), V8VarConverter::kAllowObjectVars);
    PepperTryCatchForTest try_catch(instance2.get(), &converter);
    // Make an object var.
    ppapi::ScopedPPVar var = try_catch.FromV8(MyObject::Create(test_isolate));
    EXPECT_EQ(1, g_v8objects_alive);
    EXPECT_EQ(1, tracker().GetLiveV8ObjectVarsForTest(pp_instance2));
    // Purposely leak the var.
    var.Release();
  }

  // Free the instance, this should release the ObjectVar.
  instance2 = nullptr;
  EXPECT_EQ(0, tracker().GetLiveV8ObjectVarsForTest(pp_instance2));
}

// Make sure that using the same v8 object should give the same PP_Var
// each time.
TEST_F(HostVarTrackerTest, ReuseVar) {
  V8VarConverter converter(
      instance()->pp_instance(), V8VarConverter::kAllowObjectVars);
  PepperTryCatchForTest try_catch(instance(), &converter);

  v8::Local<v8::Value> v8_object = MyObject::Create(v8::Isolate::GetCurrent());
  ppapi::ScopedPPVar pp_object1 = try_catch.FromV8(v8_object);
  ppapi::ScopedPPVar pp_object2 = try_catch.FromV8(v8_object);

  // The two results should be the same.
  EXPECT_EQ(pp_object1.get().value.as_id, pp_object2.get().value.as_id);

  // The objects should be able to get us back to the associated v8 object.
  {
    scoped_refptr<V8ObjectVar> check_object(
        V8ObjectVar::FromPPVar(pp_object1.get()));
    ASSERT_TRUE(check_object.get());
    EXPECT_EQ(instance(), check_object->instance());
    EXPECT_EQ(v8_object, check_object->GetHandle());
  }

  // Remove both of the refs we made above.
  pp_object1 = ppapi::ScopedPPVar();
  pp_object2 = ppapi::ScopedPPVar();

  // Releasing the resource should free the internal ref, and so making a new
  // one now should generate a new ID.
  ppapi::ScopedPPVar pp_object3 = try_catch.FromV8(v8_object);
  EXPECT_NE(pp_object1.get().value.as_id, pp_object3.get().value.as_id);
}

}  // namespace content