Roll WebRTC 9745:9761, Libjingle 9742:9761
[chromium-blink-merge.git] / extensions / renderer / gc_callback_unittest.cc
blob396e32267a76c9a7207d6405ab7c0322db3c9853
1 // Copyright 2015 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.
5 #include "base/bind.h"
6 #include "base/memory/weak_ptr.h"
7 #include "base/message_loop/message_loop.h"
8 #include "extensions/common/extension.h"
9 #include "extensions/common/extension_set.h"
10 #include "extensions/common/features/feature.h"
11 #include "extensions/renderer/gc_callback.h"
12 #include "extensions/renderer/scoped_web_frame.h"
13 #include "extensions/renderer/script_context.h"
14 #include "extensions/renderer/script_context_set.h"
15 #include "gin/function_template.h"
16 #include "gin/public/context_holder.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 #include "third_party/WebKit/public/web/WebFrame.h"
19 #include "v8/include/v8.h"
21 namespace extensions {
22 namespace {
24 void SetToTrue(bool* value) {
25 if (*value)
26 ADD_FAILURE() << "Value is already true";
27 *value = true;
30 class GCCallbackTest : public testing::Test {
31 public:
32 GCCallbackTest() : script_context_set_(&active_extensions_) {}
34 protected:
35 base::MessageLoop& message_loop() { return message_loop_; }
37 ScriptContextSet& script_context_set() { return script_context_set_; }
39 v8::Local<v8::Context> v8_context() {
40 return v8::Local<v8::Context>::New(v8::Isolate::GetCurrent(), v8_context_);
43 ScriptContext* RegisterScriptContext() {
44 // No extension group or world ID.
45 return script_context_set_.Register(
46 web_frame_.frame(),
47 v8::Local<v8::Context>::New(v8::Isolate::GetCurrent(), v8_context_), 0,
48 0);
51 void RequestGarbageCollection() {
52 v8::Isolate::GetCurrent()->RequestGarbageCollectionForTesting(
53 v8::Isolate::kFullGarbageCollection);
56 private:
57 void SetUp() override {
58 v8::Isolate* isolate = v8::Isolate::GetCurrent();
59 v8::HandleScope handle_scope(isolate);
60 v8::Local<v8::Context> local_v8_context = v8::Context::New(isolate);
61 v8_context_.Reset(isolate, local_v8_context);
62 // ScriptContexts rely on gin.
63 gin_context_holder_.reset(new gin::ContextHolder(isolate));
64 gin_context_holder_->SetContext(local_v8_context);
67 void TearDown() override {
68 gin_context_holder_.reset();
69 v8_context_.Reset();
70 RequestGarbageCollection();
73 base::MessageLoop message_loop_;
74 ScopedWebFrame web_frame_; // (this will construct the v8::Isolate)
75 ExtensionIdSet active_extensions_;
76 ScriptContextSet script_context_set_;
77 v8::Global<v8::Context> v8_context_;
78 scoped_ptr<gin::ContextHolder> gin_context_holder_;
80 DISALLOW_COPY_AND_ASSIGN(GCCallbackTest);
83 TEST_F(GCCallbackTest, GCBeforeContextInvalidated) {
84 v8::Isolate* isolate = v8::Isolate::GetCurrent();
85 v8::HandleScope handle_scope(isolate);
86 v8::Context::Scope context_scope(v8_context());
88 ScriptContext* script_context = RegisterScriptContext();
90 bool callback_invoked = false;
91 bool fallback_invoked = false;
94 // Nest another HandleScope so that |object| and |unreachable_function|'s
95 // handles will be garbage collected.
96 v8::HandleScope handle_scope(isolate);
97 v8::Local<v8::Object> object = v8::Object::New(isolate);
98 v8::Local<v8::FunctionTemplate> unreachable_function =
99 gin::CreateFunctionTemplate(isolate,
100 base::Bind(SetToTrue, &callback_invoked));
101 // The GCCallback will delete itself, or memory tests will complain.
102 new GCCallback(script_context, object, unreachable_function->GetFunction(),
103 base::Bind(SetToTrue, &fallback_invoked));
106 // Trigger a GC. Only the callback should be invoked.
107 RequestGarbageCollection();
108 message_loop().RunUntilIdle();
110 EXPECT_TRUE(callback_invoked);
111 EXPECT_FALSE(fallback_invoked);
113 // Invalidate the context. The fallback should not be invoked because the
114 // callback was already invoked.
115 script_context_set().Remove(script_context);
116 message_loop().RunUntilIdle();
118 EXPECT_FALSE(fallback_invoked);
121 TEST_F(GCCallbackTest, ContextInvalidatedBeforeGC) {
122 v8::Isolate* isolate = v8::Isolate::GetCurrent();
123 v8::HandleScope handle_scope(isolate);
124 v8::Context::Scope context_scope(v8_context());
126 ScriptContext* script_context = RegisterScriptContext();
128 bool callback_invoked = false;
129 bool fallback_invoked = false;
132 // Nest another HandleScope so that |object| and |unreachable_function|'s
133 // handles will be garbage collected.
134 v8::HandleScope handle_scope(isolate);
135 v8::Local<v8::Object> object = v8::Object::New(isolate);
136 v8::Local<v8::FunctionTemplate> unreachable_function =
137 gin::CreateFunctionTemplate(isolate,
138 base::Bind(SetToTrue, &callback_invoked));
139 // The GCCallback will delete itself, or memory tests will complain.
140 new GCCallback(script_context, object, unreachable_function->GetFunction(),
141 base::Bind(SetToTrue, &fallback_invoked));
144 // Invalidate the context. Only the fallback should be invoked.
145 script_context_set().Remove(script_context);
146 message_loop().RunUntilIdle();
148 EXPECT_FALSE(callback_invoked);
149 EXPECT_TRUE(fallback_invoked);
151 // Trigger a GC. The callback should not be invoked because the fallback was
152 // already invoked.
153 RequestGarbageCollection();
154 message_loop().RunUntilIdle();
156 EXPECT_FALSE(callback_invoked);
159 } // namespace
160 } // namespace extensions