1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/*
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CppBoundClass class:
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  This base class serves as a parent for C++ classes designed to be bound to
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  JavaScript objects.
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Subclasses should define the constructor to build the property and method
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  lists needed to bind this class to a JS object.  They should also declare
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  and define member variables and methods to be exposed to JS through
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  that object.
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  See cpp_binding_example.{h|cc} for an example.
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch*/
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#ifndef WEBKIT_GLUE_CPP_BOUNDCLASS_H__
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define WEBKIT_GLUE_CPP_BOUNDCLASS_H__
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <map>
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <vector>
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "webkit/glue/cpp_variant.h"
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/callback.h"
27ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h"
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace WebKit {
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass WebFrame;
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef std::vector<CppVariant> CppArgumentList;
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// CppBoundClass lets you map Javascript method calls and property accesses
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// directly to C++ method calls and CppVariant* variable access.
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass CppBoundClass {
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  class PropertyCallback {
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   public:
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    virtual ~PropertyCallback() { }
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Sets |value| to the value of the property. Returns false in case of
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // failure. |value| is always non-NULL.
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    virtual bool GetValue(CppVariant* value) = 0;
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // sets the property value to |value|. Returns false in case of failure.
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    virtual bool SetValue(const CppVariant& value) = 0;
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The constructor should call BindMethod, BindProperty, and
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // SetFallbackMethod as needed to set up the methods, properties, and
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // fallback method.
543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  CppBoundClass();
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual ~CppBoundClass();
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Return a CppVariant representing this class, for use with BindProperty().
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The variant type is guaranteed to be NPVariantType_Object.
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CppVariant* GetAsCppVariant();
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Given a WebFrame, BindToJavascript builds the NPObject that will represent
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the class and binds it to the frame's window under the given name.  This
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // should generally be called from the WebView delegate's
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // WindowObjectCleared(). A class so bound will be accessible to JavaScript
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // as window.<classname>. The owner of the CppBoundObject is responsible for
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // keeping the object around while the frame is alive, and for destroying it
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // afterwards.
6821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  void BindToJavascript(WebKit::WebFrame* frame, const std::string& classname);
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The type of callbacks.
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  typedef Callback2<const CppArgumentList&, CppVariant*>::Type Callback;
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  typedef Callback1<CppVariant*>::Type GetterCallback;
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Used by a test.  Returns true if a method with name |name| exists,
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // regardless of whether a fallback is registered.
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool IsMethodRegistered(const std::string& name) const;
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protected:
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Bind the Javascript method called |name| to the C++ callback |callback|.
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void BindCallback(const std::string& name, Callback* callback);
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // A wrapper for BindCallback, to simplify the common case of binding a
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // method on the current object.  Though not verified here, |method|
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // must be a method of this CppBoundClass subclass.
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  template<typename T>
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void BindMethod(const std::string& name,
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      void (T::*method)(const CppArgumentList&, CppVariant*)) {
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Callback* callback =
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NewCallback<T, const CppArgumentList&, CppVariant*>(
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            static_cast<T*>(this), method);
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    BindCallback(name, callback);
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Bind Javascript property |name| to the C++ getter callback |callback|.
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This can be used to create read-only properties.
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void BindGetterCallback(const std::string& name, GetterCallback* callback);
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // A wrapper for BindGetterCallback, to simplify the common case of binding a
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // property on the current object.  Though not verified here, |method|
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // must be a method of this CppBoundClass subclass.
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  template<typename T>
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void BindProperty(const std::string& name, void (T::*method)(CppVariant*)) {
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GetterCallback* callback =
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NewCallback<T, CppVariant*>(static_cast<T*>(this), method);
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    BindGetterCallback(name, callback);
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Bind the Javascript property called |name| to a CppVariant |prop|.
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void BindProperty(const std::string& name, CppVariant* prop);
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Bind Javascript property called |name| to a PropertyCallback |callback|.
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // CppBoundClass assumes control over the life time of the |callback|.
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void BindProperty(const std::string& name, PropertyCallback* callback);
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Set the fallback callback, which is called when when a callback is
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // invoked that isn't bound.
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If it is NULL (its default value), a JavaScript exception is thrown in
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // that case (as normally expected). If non NULL, the fallback method is
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // invoked and the script continues its execution.
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Passing NULL for |callback| clears out any existing binding.
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // It is used for tests and should probably only be used in such cases
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // as it may cause unexpected behaviors (a JavaScript object with a
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // fallback always returns true when checked for a method's
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // existence).
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void BindFallbackCallback(Callback* fallback_callback) {
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    fallback_callback_.reset(fallback_callback);
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // A wrapper for BindFallbackCallback, to simplify the common case of
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // binding a method on the current object.  Though not verified here,
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // |method| must be a method of this CppBoundClass subclass.
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Passing NULL for |method| clears out any existing binding.
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  template<typename T>
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void BindFallbackMethod(
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      void (T::*method)(const CppArgumentList&, CppVariant*)) {
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (method) {
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      Callback* callback =
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          NewCallback<T, const CppArgumentList&, CppVariant*>(
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch              static_cast<T*>(this), method);
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      BindFallbackCallback(callback);
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      BindFallbackCallback(NULL);
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Some fields are protected because some tests depend on accessing them,
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // but otherwise they should be considered private.
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  typedef std::map<NPIdentifier, PropertyCallback*> PropertyList;
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  typedef std::map<NPIdentifier, Callback*> MethodList;
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // These maps associate names with property and method pointers to be
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // exposed to JavaScript.
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PropertyList properties_;
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MethodList methods_;
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The callback gets invoked when a call is made to an nonexistent method.
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<Callback> fallback_callback_;
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // NPObject callbacks.
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  friend struct CppNPObject;
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool HasMethod(NPIdentifier ident) const;
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool Invoke(NPIdentifier ident, const NPVariant* args, size_t arg_count,
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch              NPVariant* result);
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool HasProperty(NPIdentifier ident) const;
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool GetProperty(NPIdentifier ident, NPVariant* result) const;
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool SetProperty(NPIdentifier ident, const NPVariant* value);
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // A lazily-initialized CppVariant representing this class.  We retain 1
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // reference to this object, and it is released on deletion.
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CppVariant self_variant_;
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // True if our np_object has been bound to a WebFrame, in which case it must
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // be unregistered with V8 when we delete it.
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool bound_to_frame_;
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DISALLOW_COPY_AND_ASSIGN(CppBoundClass);
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif  // CPP_BOUNDCLASS_H__
181