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 MOJO_EDK_JS_HANDLE_H_
6 #define MOJO_EDK_JS_HANDLE_H_
7 
8 #include <stdint.h>
9 
10 #include "base/observer_list.h"
11 #include "gin/converter.h"
12 #include "gin/handle.h"
13 #include "gin/wrappable.h"
14 #include "mojo/public/cpp/system/core.h"
15 
16 namespace mojo {
17 namespace edk {
18 namespace js {
19 
20 class HandleCloseObserver;
21 
22 // Wrapper for mojo Handles exposed to JavaScript. This ensures the Handle
23 // is Closed when its JS object is garbage collected.
24 class HandleWrapper : public gin::Wrappable<HandleWrapper> {
25  public:
26   static gin::WrapperInfo kWrapperInfo;
27 
Create(v8::Isolate * isolate,MojoHandle handle)28   static gin::Handle<HandleWrapper> Create(v8::Isolate* isolate,
29                                            MojoHandle handle) {
30     return gin::CreateHandle(isolate, new HandleWrapper(handle));
31   }
32 
get()33   mojo::Handle get() const { return handle_.get(); }
release()34   mojo::Handle release() { return handle_.release(); }
35   void Close();
36 
37   void AddCloseObserver(HandleCloseObserver* observer);
38   void RemoveCloseObserver(HandleCloseObserver* observer);
39 
40  protected:
41   HandleWrapper(MojoHandle handle);
42   ~HandleWrapper() override;
43   void NotifyCloseObservers();
44 
45   mojo::ScopedHandle handle_;
46   base::ObserverList<HandleCloseObserver> close_observers_;
47 };
48 
49 }  // namespace js
50 }  // namespace edk
51 }  // namespace mojo
52 
53 namespace gin {
54 
55 // Note: It's important to use this converter rather than the one for
56 // MojoHandle, since that will do a simple int32_t conversion. It's unfortunate
57 // there's no way to prevent against accidental use.
58 // TODO(mpcomplete): define converters for all Handle subtypes.
59 template<>
60 struct Converter<mojo::Handle> {
61   static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
62                                     const mojo::Handle& val);
63   static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val,
64                      mojo::Handle* out);
65 };
66 
67 template<>
68 struct Converter<mojo::MessagePipeHandle> {
69   static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
70                                     mojo::MessagePipeHandle val);
71   static bool FromV8(v8::Isolate* isolate,
72                      v8::Handle<v8::Value> val,
73                      mojo::MessagePipeHandle* out);
74 };
75 
76 // We need to specialize the normal gin::Handle converter in order to handle
77 // converting |null| to a wrapper for an empty mojo::Handle.
78 template <>
79 struct Converter<gin::Handle<mojo::edk::js::HandleWrapper>> {
80   static v8::Handle<v8::Value> ToV8(
81       v8::Isolate* isolate,
82       const gin::Handle<mojo::edk::js::HandleWrapper>& val) {
83     return val.ToV8();
84   }
85 
86   static bool FromV8(v8::Isolate* isolate,
87                      v8::Handle<v8::Value> val,
88                      gin::Handle<mojo::edk::js::HandleWrapper>* out) {
89     if (val->IsNull()) {
90       *out = mojo::edk::js::HandleWrapper::Create(isolate, MOJO_HANDLE_INVALID);
91       return true;
92     }
93 
94     mojo::edk::js::HandleWrapper* object = NULL;
95     if (!Converter<mojo::edk::js::HandleWrapper*>::FromV8(isolate, val,
96                                                           &object)) {
97       return false;
98     }
99     *out = gin::Handle<mojo::edk::js::HandleWrapper>(val, object);
100     return true;
101   }
102 };
103 
104 }  // namespace gin
105 
106 #endif  // MOJO_EDK_JS_HANDLE_H_
107