1// Copyright 2014 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.
4
5#ifndef EXTENSIONS_RENDERER_SCOPED_PERSISTENT_H_
6#define EXTENSIONS_RENDERER_SCOPED_PERSISTENT_H_
7
8#include "base/logging.h"
9#include "v8/include/v8.h"
10
11namespace extensions {
12
13// A v8::Persistent handle to a V8 value which destroys and clears the
14// underlying handle on destruction.
15template <typename T>
16class ScopedPersistent {
17 public:
18  ScopedPersistent() {}
19
20  explicit ScopedPersistent(v8::Handle<T> handle) { reset(handle); }
21
22  ~ScopedPersistent() { reset(); }
23
24  void reset(v8::Handle<T> handle) {
25    if (!handle.IsEmpty())
26      handle_.Reset(GetIsolate(handle), handle);
27    else
28      reset();
29  }
30
31  void reset() { handle_.Reset(); }
32
33  bool IsEmpty() const { return handle_.IsEmpty(); }
34
35  v8::Handle<T> NewHandle() const {
36    if (handle_.IsEmpty())
37      return v8::Local<T>();
38    return v8::Local<T>::New(GetIsolate(handle_), handle_);
39  }
40
41  v8::Handle<T> NewHandle(v8::Isolate* isolate) const {
42    if (handle_.IsEmpty())
43      return v8::Local<T>();
44    return v8::Local<T>::New(isolate, handle_);
45  }
46
47  template <typename P>
48  void SetWeak(P* parameters,
49               typename v8::WeakCallbackData<T, P>::Callback callback) {
50    handle_.SetWeak(parameters, callback);
51  }
52
53 private:
54  template <typename U>
55  static v8::Isolate* GetIsolate(v8::Handle<U> object_handle) {
56    // Only works for v8::Object and its subclasses. Add specialisations for
57    // anything else.
58    if (!object_handle.IsEmpty())
59      return GetIsolate(object_handle->CreationContext());
60    return v8::Isolate::GetCurrent();
61  }
62  static v8::Isolate* GetIsolate(v8::Handle<v8::Context> context_handle) {
63    if (!context_handle.IsEmpty())
64      return context_handle->GetIsolate();
65    return v8::Isolate::GetCurrent();
66  }
67  static v8::Isolate* GetIsolate(
68      v8::Handle<v8::ObjectTemplate> template_handle) {
69    return v8::Isolate::GetCurrent();
70  }
71
72  v8::Persistent<T> handle_;
73
74  DISALLOW_COPY_AND_ASSIGN(ScopedPersistent);
75};
76
77}  // namespace extensions
78
79#endif  // EXTENSIONS_RENDERER_SCOPED_PERSISTENT_H_
80