15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file contains definitions for CppBoundClass
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Here's the control flow of a JS method getting forwarded to a class.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Something calls our NPObject with a function like "Invoke".
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - CppNPObject's static invoke() function forwards it to its attached
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   CppBoundClass's Invoke() method.
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - CppBoundClass has then overridden Invoke() to look up the function
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   name in its internal map of methods, and then calls the appropriate
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   method.
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "webkit/renderer/cpp_bound_class.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebBindings.h"
227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebFrame.h"
23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebString.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebBindings;
26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebFrame;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace webkit_glue {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CppVariantPropertyCallback : public CppBoundClass::PropertyCallback {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CppVariantPropertyCallback(CppVariant* value) : value_(value) { }
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool GetValue(CppVariant* value) OVERRIDE {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    value->Set(*value_);
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool SetValue(const CppVariant& value) OVERRIDE {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    value_->Set(value);
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CppVariant* value_;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class GetterPropertyCallback : public CppBoundClass::PropertyCallback {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public:
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetterPropertyCallback(const CppBoundClass::GetterCallback& callback)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : callback_(callback) { }
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool GetValue(CppVariant* value) OVERRIDE {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback_.Run(value);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool SetValue(const CppVariant& value) OVERRIDE {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)private:
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CppBoundClass::GetterCallback callback_;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Our special NPObject type.  We extend an NPObject with a pointer to a
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CppBoundClass, which is just a C++ interface that we forward all NPObject
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// callbacks to.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct CppNPObject {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NPObject parent;  // This must be the first field in the struct.
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CppBoundClass* bound_class;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // All following objects and functions are static, and just used to interface
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // with NPObject/NPClass.
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // An NPClass associates static functions of CppNPObject with the
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // function pointers used by the JS runtime.
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static NPClass np_class_;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allocate a new NPObject with the specified class.
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static NPObject* allocate(NPP npp, NPClass* aClass);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Free an object.
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void deallocate(NPObject* obj);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true if the C++ class associated with this NPObject exposes the
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // given property.  Called by the JS runtime.
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static bool hasProperty(NPObject *obj, NPIdentifier ident);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true if the C++ class associated with this NPObject exposes the
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // given method.  Called by the JS runtime.
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static bool hasMethod(NPObject *obj, NPIdentifier ident);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the given method is exposed by the C++ class associated with this
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NPObject, invokes it with the given args and returns a result.  Otherwise,
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // returns "undefined" (in the JavaScript sense).  Called by the JS runtime.
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static bool invoke(NPObject *obj, NPIdentifier ident,
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const NPVariant *args, uint32_t arg_count,
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     NPVariant *result);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the given property is exposed by the C++ class associated with this
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NPObject, returns its value.  Otherwise, returns "undefined" (in the
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // JavaScript sense).  Called by the JS runtime.
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static bool getProperty(NPObject *obj, NPIdentifier ident,
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          NPVariant *result);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the given property is exposed by the C++ class associated with this
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NPObject, sets its value.  Otherwise, does nothing. Called by the JS
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // runtime.
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static bool setProperty(NPObject *obj, NPIdentifier ident,
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const NPVariant *value);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Build CppNPObject's static function pointers into an NPClass, for use
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in constructing NPObjects for the C++ classes.
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NPClass CppNPObject::np_class_ = {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NP_CLASS_STRUCT_VERSION,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CppNPObject::allocate,
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CppNPObject::deallocate,
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* NPInvalidateFunctionPtr */ NULL,
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CppNPObject::hasMethod,
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CppNPObject::invoke,
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* NPInvokeDefaultFunctionPtr */ NULL,
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CppNPObject::hasProperty,
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CppNPObject::getProperty,
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CppNPObject::setProperty,
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* NPRemovePropertyFunctionPtr */ NULL
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* static */ NPObject* CppNPObject::allocate(NPP npp, NPClass* aClass) {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CppNPObject* obj = new CppNPObject;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // obj->parent will be initialized by the NPObject code calling this.
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  obj->bound_class = NULL;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return &obj->parent;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* static */ void CppNPObject::deallocate(NPObject* np_obj) {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CppNPObject* obj = reinterpret_cast<CppNPObject*>(np_obj);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete obj;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* static */ bool CppNPObject::hasMethod(NPObject* np_obj,
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         NPIdentifier ident) {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CppNPObject* obj = reinterpret_cast<CppNPObject*>(np_obj);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return obj->bound_class->HasMethod(ident);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* static */ bool CppNPObject::hasProperty(NPObject* np_obj,
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           NPIdentifier ident) {
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CppNPObject* obj = reinterpret_cast<CppNPObject*>(np_obj);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return obj->bound_class->HasProperty(ident);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* static */ bool CppNPObject::invoke(NPObject* np_obj, NPIdentifier ident,
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      const NPVariant* args, uint32_t arg_count,
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      NPVariant* result) {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CppNPObject* obj = reinterpret_cast<CppNPObject*>(np_obj);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return obj->bound_class->Invoke(ident, args, arg_count, result);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* static */ bool CppNPObject::getProperty(NPObject* np_obj,
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           NPIdentifier ident,
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           NPVariant* result) {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CppNPObject* obj = reinterpret_cast<CppNPObject*>(np_obj);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return obj->bound_class->GetProperty(ident, result);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* static */ bool CppNPObject::setProperty(NPObject* np_obj,
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           NPIdentifier ident,
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           const NPVariant* value) {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CppNPObject* obj = reinterpret_cast<CppNPObject*>(np_obj);
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return obj->bound_class->SetProperty(ident, value);
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)CppBoundClass::CppBoundClass() : bound_to_frame_(false), npp_(new NPP_t) {
18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  WebBindings::registerObjectOwner(npp_.get());
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CppBoundClass::~CppBoundClass() {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteValues(&properties_);
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // TODO(wez): Remove once crrev.com/14019005 lands.
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (bound_to_frame_)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebBindings::unregisterObject(NPVARIANT_TO_OBJECT(self_variant_));
19090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
19190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  WebBindings::unregisterObjectOwner(npp_.get());
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CppBoundClass::HasMethod(NPIdentifier ident) const {
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (methods_.find(ident) != methods_.end());
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CppBoundClass::HasProperty(NPIdentifier ident) const {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (properties_.find(ident) != properties_.end());
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CppBoundClass::Invoke(NPIdentifier ident,
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const NPVariant* args,
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           size_t arg_count,
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           NPVariant* result) {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MethodList::const_iterator method = methods_.find(ident);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Callback callback;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (method == methods_.end()) {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!fallback_callback_.is_null()) {
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback = fallback_callback_;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VOID_TO_NPVARIANT(*result);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback = method->second;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Build a CppArgumentList argument vector from the NPVariants coming in.
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CppArgumentList cpp_args(arg_count);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < arg_count; i++)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cpp_args[i].Set(args[i]);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CppVariant cpp_result;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.Run(cpp_args, &cpp_result);
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cpp_result.CopyToNPVariant(result);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CppBoundClass::GetProperty(NPIdentifier ident, NPVariant* result) const {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PropertyList::const_iterator callback = properties_.find(ident);
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (callback == properties_.end()) {
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VOID_TO_NPVARIANT(*result);
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CppVariant cpp_value;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!callback->second->GetValue(&cpp_value))
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cpp_value.CopyToNPVariant(result);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CppBoundClass::SetProperty(NPIdentifier ident,
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const NPVariant* value) {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PropertyList::iterator callback = properties_.find(ident);
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (callback == properties_.end())
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CppVariant cpp_value;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cpp_value.Set(*value);
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (*callback).second->SetValue(cpp_value);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CppBoundClass::BindCallback(const std::string& name,
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const Callback& callback) {
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NPIdentifier ident = WebBindings::getStringIdentifier(name.c_str());
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (callback.is_null()) {
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    methods_.erase(ident);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  methods_[ident] = callback;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CppBoundClass::BindGetterCallback(const std::string& name,
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const GetterCallback& callback) {
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PropertyCallback* property_callback = callback.is_null() ?
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NULL : new GetterPropertyCallback(callback);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BindProperty(name, property_callback);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CppBoundClass::BindProperty(const std::string& name, CppVariant* prop) {
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PropertyCallback* property_callback = prop == NULL ?
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NULL : new CppVariantPropertyCallback(prop);
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BindProperty(name, property_callback);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CppBoundClass::BindProperty(const std::string& name,
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 PropertyCallback* callback) {
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NPIdentifier ident = WebBindings::getStringIdentifier(name.c_str());
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PropertyList::iterator old_callback = properties_.find(ident);
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (old_callback != properties_.end()) {
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete old_callback->second;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (callback == NULL) {
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      properties_.erase(old_callback);
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  properties_[ident] = callback;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CppBoundClass::IsMethodRegistered(const std::string& name) const {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NPIdentifier ident = WebBindings::getStringIdentifier(name.c_str());
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MethodList::const_iterator callback = methods_.find(ident);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (callback != methods_.end());
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CppVariant* CppBoundClass::GetAsCppVariant() {
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!self_variant_.isObject()) {
30590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Create an NPObject using our static NPClass.  The first argument has type
30690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // NPP, but is only used to track object ownership, so passing this is fine.
30790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    NPObject* np_obj = WebBindings::createObject(
30890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        npp_.get(), &CppNPObject::np_class_);
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CppNPObject* obj = reinterpret_cast<CppNPObject*>(np_obj);
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    obj->bound_class = this;
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self_variant_.Set(np_obj);
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebBindings::releaseObject(np_obj);  // CppVariant takes the reference.
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(self_variant_.isObject());
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return &self_variant_;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CppBoundClass::BindToJavascript(WebFrame* frame,
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     const std::string& classname) {
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // BindToWindowObject will take its own reference to the NPObject, and clean
32190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // up after itself. It will also (indirectly) register the object with V8,
32290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // against an owner pointer we supply, so we must register that as an owner,
32390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // and unregister when we teardown.
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frame->bindToWindowObject(ASCIIToUTF16(classname),
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            NPVARIANT_TO_OBJECT(*GetAsCppVariant()));
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bound_to_frame_ = true;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace webkit_glue
330