diff options
Diffstat (limited to 'chromium/extensions/renderer/gc_callback.cc')
-rw-r--r-- | chromium/extensions/renderer/gc_callback.cc | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/chromium/extensions/renderer/gc_callback.cc b/chromium/extensions/renderer/gc_callback.cc new file mode 100644 index 00000000000..46b7f8acdf1 --- /dev/null +++ b/chromium/extensions/renderer/gc_callback.cc @@ -0,0 +1,58 @@ +// Copyright 2015 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/gc_callback.h" + +#include "base/bind.h" +#include "base/message_loop/message_loop.h" +#include "extensions/renderer/script_context.h" + +namespace extensions { + +GCCallback::GCCallback(ScriptContext* context, + const v8::Local<v8::Object>& object, + const v8::Local<v8::Function>& callback, + const base::Closure& fallback) + : context_(context), + object_(context->isolate(), object), + callback_(context->isolate(), callback), + fallback_(fallback), + weak_ptr_factory_(this) { + object_.SetWeak(this, OnObjectGC, v8::WeakCallbackType::kParameter); + context->AddInvalidationObserver(base::Bind(&GCCallback::OnContextInvalidated, + weak_ptr_factory_.GetWeakPtr())); +} + +GCCallback::~GCCallback() {} + +// static +void GCCallback::OnObjectGC(const v8::WeakCallbackInfo<GCCallback>& data) { + // Usually FirstWeakCallback should do nothing other than reset |object_| + // and then set a second weak callback to run later. We can sidestep that, + // because posting a task to the current message loop is all but free - but + // DO NOT add any more work to this method. The only acceptable place to add + // code is RunCallback. + GCCallback* self = data.GetParameter(); + self->object_.Reset(); + base::MessageLoop::current()->PostTask( + FROM_HERE, base::Bind(&GCCallback::RunCallback, + self->weak_ptr_factory_.GetWeakPtr())); +} + +void GCCallback::RunCallback() { + fallback_.Reset(); + v8::Isolate* isolate = context_->isolate(); + v8::HandleScope handle_scope(isolate); + context_->CallFunction(v8::Local<v8::Function>::New(isolate, callback_)); + delete this; +} + +void GCCallback::OnContextInvalidated() { + if (!fallback_.is_null()) { + fallback_.Run(); + delete this; + } +} + +} // namespace extensions |