123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- // Copyright 2016 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 "extensions/renderer/bindings/api_binding_test.h"
- #include "base/threading/thread_task_runner_handle.h"
- #include "gin/array_buffer.h"
- #include "gin/public/context_holder.h"
- #include "gin/public/isolate_holder.h"
- #include "gin/v8_initializer.h"
- namespace extensions {
- APIBindingTest::APIBindingTest() {}
- APIBindingTest::~APIBindingTest() {}
- v8::ExtensionConfiguration* APIBindingTest::GetV8ExtensionConfiguration() {
- return nullptr;
- }
- void APIBindingTest::SetUp() {
- test_js_runner_ = CreateTestJSRunner();
- // Much of this initialization is stolen from the somewhat-similar
- // gin::V8Test.
- #ifdef V8_USE_EXTERNAL_STARTUP_DATA
- gin::V8Initializer::LoadV8Snapshot();
- #endif
- gin::IsolateHolder::Initialize(gin::IsolateHolder::kStrictMode,
- gin::ArrayBufferAllocator::SharedInstance());
- isolate_holder_ = std::make_unique<gin::IsolateHolder>(
- base::ThreadTaskRunnerHandle::Get(),
- gin::IsolateHolder::IsolateType::kTest);
- isolate()->Enter();
- v8::HandleScope handle_scope(isolate());
- v8::Local<v8::Context> context =
- v8::Context::New(isolate(), GetV8ExtensionConfiguration());
- context->Enter();
- main_context_holder_ = std::make_unique<gin::ContextHolder>(isolate());
- main_context_holder_->SetContext(context);
- }
- void APIBindingTest::TearDown() {
- if (main_context_holder_ || !additional_context_holders_.empty()) {
- DisposeAllContexts();
- } else {
- // The context was already deleted (as through DisposeContext()), but we
- // still need to garbage collect.
- RunGarbageCollection();
- }
- isolate()->Exit();
- isolate_holder_.reset();
- test_js_runner_.reset();
- }
- void APIBindingTest::DisposeAllContexts() {
- auto dispose_and_check_context =
- [this](std::unique_ptr<gin::ContextHolder>& holder, bool exit) {
- // Check for leaks - a weak handle to a context is invalidated on
- // context destruction, so resetting the context should reset the
- // handle.
- v8::Global<v8::Context> weak_context;
- {
- v8::HandleScope handle_scope(isolate());
- v8::Local<v8::Context> context = holder->context();
- weak_context.Reset(isolate(), context);
- weak_context.SetWeak();
- OnWillDisposeContext(context);
- if (exit)
- context->Exit();
- }
- holder.reset();
- // Garbage collect everything so that we find any issues where we might
- // be double-freeing.
- RunGarbageCollection();
- // The context should have been deleted.
- // (ASSERT_TRUE is not used, so that Isolate::Exit is still called.)
- EXPECT_TRUE(weak_context.IsEmpty());
- };
- for (auto& context_holder : additional_context_holders_)
- dispose_and_check_context(context_holder, false);
- additional_context_holders_.clear();
- if (main_context_holder_)
- dispose_and_check_context(main_context_holder_, true);
- }
- v8::Local<v8::Context> APIBindingTest::AddContext() {
- auto holder = std::make_unique<gin::ContextHolder>(isolate());
- v8::Local<v8::Context> context =
- v8::Context::New(isolate(), GetV8ExtensionConfiguration());
- holder->SetContext(context);
- additional_context_holders_.push_back(std::move(holder));
- return context;
- }
- v8::Local<v8::Context> APIBindingTest::MainContext() {
- return main_context_holder_->context();
- }
- void APIBindingTest::DisposeContext(v8::Local<v8::Context> context) {
- if (main_context_holder_ && context == main_context_holder_->context()) {
- context->Exit();
- OnWillDisposeContext(context);
- main_context_holder_.reset();
- return;
- }
- auto iter = std::find_if(
- additional_context_holders_.begin(), additional_context_holders_.end(),
- [context](const std::unique_ptr<gin::ContextHolder>& holder) {
- return holder->context() == context;
- });
- ASSERT_TRUE(iter != additional_context_holders_.end())
- << "Could not find context";
- OnWillDisposeContext(context);
- additional_context_holders_.erase(iter);
- }
- void APIBindingTest::RunGarbageCollection() {
- // '5' is a magic number stolen from Blink; arbitrarily large enough to
- // hopefully clean up all the various paths.
- for (int i = 0; i < 5; ++i) {
- isolate()->RequestGarbageCollectionForTesting(
- v8::Isolate::kFullGarbageCollection);
- }
- }
- std::unique_ptr<TestJSRunner::Scope> APIBindingTest::CreateTestJSRunner() {
- return std::make_unique<TestJSRunner::Scope>(
- std::make_unique<TestJSRunner>());
- }
- v8::Isolate* APIBindingTest::isolate() {
- return isolate_holder_->isolate();
- }
- } // namespace extensions
|