summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--webkit/glue/cpp_bound_class.cc41
-rw-r--r--webkit/glue/cpp_bound_class.h17
-rw-r--r--webkit/glue/cpp_bound_class_unittest.cc27
3 files changed, 60 insertions, 25 deletions
diff --git a/webkit/glue/cpp_bound_class.cc b/webkit/glue/cpp_bound_class.cc
index 23ef80a..ea06dd2 100644
--- a/webkit/glue/cpp_bound_class.cc
+++ b/webkit/glue/cpp_bound_class.cc
@@ -146,14 +146,11 @@ CppBoundClass::~CppBoundClass() {
for (MethodList::iterator i = methods_.begin(); i != methods_.end(); ++i)
delete i->second;
- // Unregister objects we created and bound to a frame.
- for (BoundObjectList::iterator i = bound_objects_.begin();
- i != bound_objects_.end(); ++i) {
+ // Unregister ourselves if we were bound to a frame.
#if USE(V8)
- _NPN_UnregisterObject(*i);
+ if (bound_to_frame_)
+ _NPN_UnregisterObject(NPVARIANT_TO_OBJECT(self_variant_));
#endif
- NPN_ReleaseObject(*i);
- }
}
bool CppBoundClass::HasMethod(NPIdentifier ident) const {
@@ -237,22 +234,30 @@ bool CppBoundClass::IsMethodRegistered(std::string name) const {
return (callback != methods_.end());
}
+CppVariant* CppBoundClass::GetAsCppVariant() {
+ if (!self_variant_.isObject()) {
+ // Create an NPObject using our static NPClass. The first argument (a
+ // plugin's instance handle) is passed through to the allocate function
+ // directly, and we don't use it, so it's ok to be 0.
+ NPObject* np_obj = NPN_CreateObject(0, &CppNPObject::np_class_);
+ CppNPObject* obj = reinterpret_cast<CppNPObject*>(np_obj);
+ obj->bound_class = this;
+ self_variant_.Set(np_obj);
+ NPN_ReleaseObject(np_obj); // CppVariant takes the reference.
+ }
+ DCHECK(self_variant_.isObject());
+ return &self_variant_;
+}
+
void CppBoundClass::BindToJavascript(WebFrame* frame,
const std::wstring& classname) {
#if USE(JSC)
JSC::JSLock lock(false);
#endif
- // Create an NPObject using our static NPClass. The first argument (a
- // plugin's instance handle) is passed through to the allocate function
- // directly, and we don't use it, so it's ok to be 0.
- NPObject* np_obj = NPN_CreateObject(0, &CppNPObject::np_class_);
- CppNPObject* obj = reinterpret_cast<CppNPObject*>(np_obj);
- obj->bound_class = this;
-
- // BindToWindowObject will (indirectly) retain the np_object. We save it
- // so we can release it when we're destroyed.
- frame->BindToWindowObject(classname, np_obj);
- bound_objects_.push_back(np_obj);
+ // BindToWindowObject will take its own reference to the NPObject, and clean
+ // up after itself. It will also (indirectly) register the object with V8,
+ // so we must remember this so we can unregister it when we're destroyed.
+ frame->BindToWindowObject(classname, NPVARIANT_TO_OBJECT(*GetAsCppVariant()));
+ bound_to_frame_ = true;
}
-
diff --git a/webkit/glue/cpp_bound_class.h b/webkit/glue/cpp_bound_class.h
index 86008f2..a29f441 100644
--- a/webkit/glue/cpp_bound_class.h
+++ b/webkit/glue/cpp_bound_class.h
@@ -36,9 +36,13 @@ class CppBoundClass {
// The constructor should call BindMethod, BindProperty, and
// SetFallbackMethod as needed to set up the methods, properties, and
// fallback method.
- CppBoundClass() { }
+ CppBoundClass() : bound_to_frame_(false) { }
virtual ~CppBoundClass();
+ // Return a CppVariant representing this class, for use with BindProperty().
+ // The variant type is guaranteed to be NPVariantType_Object.
+ CppVariant* GetAsCppVariant();
+
// Given a WebFrame, BindToJavascript builds the NPObject that will represent
// the class and binds it to the frame's window under the given name. This
// should generally be called from the WebView delegate's
@@ -128,10 +132,13 @@ class CppBoundClass {
bool GetProperty(NPIdentifier ident, NPVariant* result) const;
bool SetProperty(NPIdentifier ident, const NPVariant* value);
- // A list of all NPObjects we created and bound in BindToJavascript(), so we
- // can clean them up when we're destroyed.
- typedef std::vector<NPObject*> BoundObjectList;
- BoundObjectList bound_objects_;
+ // A lazily-initialized CppVariant representing this class. We retain 1
+ // reference to this object, and it is released on deletion.
+ CppVariant self_variant_;
+
+ // True if our np_object has been bound to a WebFrame, in which case it must
+ // be unregistered with V8 when we delete it.
+ bool bound_to_frame_;
DISALLOW_EVIL_CONSTRUCTORS(CppBoundClass);
};
diff --git a/webkit/glue/cpp_bound_class_unittest.cc b/webkit/glue/cpp_bound_class_unittest.cc
index b080478..1f412cc 100644
--- a/webkit/glue/cpp_bound_class_unittest.cc
+++ b/webkit/glue/cpp_bound_class_unittest.cc
@@ -17,9 +17,21 @@
namespace {
+class CppBindingExampleSubObject : public CppBindingExample {
+ public:
+ CppBindingExampleSubObject() {
+ sub_value_.Set("sub!");
+ BindProperty("sub_value", &sub_value_);
+ }
+ private:
+ CppVariant sub_value_;
+};
+
+
class CppBindingExampleWithOptionalFallback : public CppBindingExample {
public:
CppBindingExampleWithOptionalFallback() {
+ BindProperty("sub_object", sub_object_.GetAsCppVariant());
}
void set_fallback_method_enabled(bool state) {
@@ -30,9 +42,11 @@ class CppBindingExampleWithOptionalFallback : public CppBindingExample {
// The fallback method does nothing, but because of it the JavaScript keeps
// running when a nonexistent method is called on an object.
- void fallbackMethod(const CppArgumentList& args,
- CppVariant* result) {
+ void fallbackMethod(const CppArgumentList& args, CppVariant* result) {
}
+
+ private:
+ CppBindingExampleSubObject sub_object_;
};
class ExampleTestShell : public TestShell {
@@ -158,6 +172,15 @@ TEST_F(CppBoundClassTest, PropertiesAreInitialized) {
CheckJavaScriptSuccess(js);
}
+TEST_F(CppBoundClassTest, SubOject) {
+ std::string js = BuildJSCondition("typeof window.example.sub_object",
+ "'object'");
+ CheckJavaScriptSuccess(js);
+
+ js = BuildJSCondition("example.sub_object.sub_value", "'sub!'");
+ CheckJavaScriptSuccess(js);
+}
+
TEST_F(CppBoundClassTest, SetAndGetProperties) {
// The property on the left will be set to the value on the right, then
// checked to make sure it holds that same value.