| // Copyright 2013 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 "gin/modules/timer.h" |
| |
| #include "base/bind.h" |
| #include "gin/object_template_builder.h" |
| #include "gin/per_context_data.h" |
| |
| namespace gin { |
| |
| namespace { |
| |
| v8::Local<v8::Private> GetHiddenPropertyName(v8::Isolate* isolate) { |
| return v8::Private::ForApi(isolate, gin::StringToV8(isolate, "::gin::Timer")); |
| } |
| |
| } // namespace |
| |
| // Timer ======================================================================= |
| |
| gin::WrapperInfo Timer::kWrapperInfo = { gin::kEmbedderNativeGin }; |
| |
| // static |
| Handle<Timer> Timer::Create(TimerType type, v8::Isolate* isolate, int delay_ms, |
| v8::Local<v8::Function> function) { |
| return CreateHandle(isolate, new Timer(isolate, type == TYPE_REPEATING, |
| delay_ms, function)); |
| } |
| |
| ObjectTemplateBuilder Timer::GetObjectTemplateBuilder(v8::Isolate* isolate) { |
| // We use Unretained() here because we directly own timer_, so we know it will |
| // be alive when these methods are called. |
| return Wrappable<Timer>::GetObjectTemplateBuilder(isolate) |
| .SetMethod("cancel", |
| base::Bind(&base::Timer::Stop, base::Unretained(&timer_))) |
| .SetMethod("reset", |
| base::Bind(&base::Timer::Reset, base::Unretained(&timer_))); |
| } |
| |
| Timer::Timer(v8::Isolate* isolate, bool repeating, int delay_ms, |
| v8::Local<v8::Function> function) |
| : timer_(false, repeating), |
| runner_(PerContextData::From( |
| isolate->GetCurrentContext())->runner()->GetWeakPtr()), |
| weak_factory_(this) { |
| GetWrapper(runner_->GetContextHolder()->isolate()) |
| ->SetPrivate(isolate->GetCurrentContext(), GetHiddenPropertyName(isolate), |
| function) |
| .FromJust(); |
| timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(delay_ms), |
| base::Bind(&Timer::OnTimerFired, weak_factory_.GetWeakPtr())); |
| } |
| |
| Timer::~Timer() { |
| } |
| |
| void Timer::OnTimerFired() { |
| // This can happen in spite of the weak callback because it is possible for |
| // a gin::Handle<> to keep this object alive past when the isolate it is part |
| // of is destroyed. |
| if (!runner_.get()) { |
| return; |
| } |
| |
| Runner::Scope scope(runner_.get()); |
| v8::Isolate* isolate = runner_->GetContextHolder()->isolate(); |
| v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast( |
| GetWrapper(isolate) |
| ->GetPrivate(runner_->GetContextHolder()->context(), |
| GetHiddenPropertyName(isolate)) |
| .ToLocalChecked()); |
| runner_->Call(function, v8::Undefined(isolate), 0, NULL); |
| } |
| |
| |
| // TimerModule ================================================================= |
| |
| const char TimerModule::kName[] = "timer"; |
| WrapperInfo TimerModule::kWrapperInfo = { kEmbedderNativeGin }; |
| |
| // static |
| Handle<TimerModule> TimerModule::Create(v8::Isolate* isolate) { |
| return CreateHandle(isolate, new TimerModule()); |
| } |
| |
| // static |
| v8::Local<v8::Value> TimerModule::GetModule(v8::Isolate* isolate) { |
| return Create(isolate)->GetWrapper(isolate); |
| } |
| |
| TimerModule::TimerModule() { |
| } |
| |
| TimerModule::~TimerModule() { |
| } |
| |
| ObjectTemplateBuilder TimerModule::GetObjectTemplateBuilder( |
| v8::Isolate* isolate) { |
| return Wrappable<TimerModule>::GetObjectTemplateBuilder(isolate) |
| .SetMethod("createOneShot", |
| base::Bind(&Timer::Create, Timer::TYPE_ONE_SHOT)) |
| .SetMethod("createRepeating", |
| base::Bind(&Timer::Create, Timer::TYPE_REPEATING)); |
| } |
| |
| } // namespace gin |