1// Copyright 2013 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 CHROME_RENDERER_EXTENSIONS_SCOPED_PERSISTENT_H_
6#define CHROME_RENDERER_EXTENSIONS_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
21  explicit ScopedPersistent(v8::Handle<T> handle) {
22    reset(handle);
23  }
24
25  ~ScopedPersistent() {
26    reset();
27  }
28
29  void reset(v8::Handle<T> handle) {
30    if (!handle.IsEmpty())
31      handle_.Reset(GetIsolate(handle), handle);
32    else
33      reset();
34  }
35
36  void reset() {
37    if (handle_.IsEmpty())
38      return;
39    handle_.Dispose();
40    handle_.Clear();
41  }
42
43  v8::Handle<T> operator->() const {
44    return get();
45  }
46
47  // TODO(dcarney): Remove this function
48  // This is an unsafe access to the underlying handle
49  v8::Handle<T> get() const {
50    return *reinterpret_cast<v8::Handle<T>*>(
51      const_cast<v8::Persistent<T>* >(&handle_));
52  }
53
54  v8::Handle<T> NewHandle() const {
55    if (handle_.IsEmpty())
56      return v8::Local<T>();
57    return v8::Local<T>::New(GetIsolate(handle_), handle_);
58  }
59
60  template<typename P>
61  void MakeWeak(P* parameters,
62                typename v8::WeakReferenceCallbacks<T, P>::Revivable callback) {
63    handle_.MakeWeak(parameters, callback);
64  }
65
66 private:
67  template <typename U>
68  static v8::Isolate* GetIsolate(v8::Handle<U> object_handle) {
69    // Only works for v8::Object and its subclasses. Add specialisations for
70    // anything else.
71    if (!object_handle.IsEmpty())
72      return GetIsolate(object_handle->CreationContext());
73    return v8::Isolate::GetCurrent();
74  }
75  static v8::Isolate* GetIsolate(v8::Handle<v8::Context> context_handle) {
76    if (!context_handle.IsEmpty())
77      return context_handle->GetIsolate();
78    return v8::Isolate::GetCurrent();
79  }
80  static v8::Isolate* GetIsolate(
81      v8::Handle<v8::ObjectTemplate> template_handle) {
82    return v8::Isolate::GetCurrent();
83  }
84
85  v8::Persistent<T> handle_;
86
87  DISALLOW_COPY_AND_ASSIGN(ScopedPersistent);
88};
89
90}  // namespace extensions
91
92#endif  // CHROME_RENDERER_EXTENSIONS_SCOPED_PERSISTENT_H_
93