blob: 46751d640b2288d2e6ca056c279f8ef07ec44675 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/renderer/browser_plugin/browser_plugin_bindings.h"
#include <string>
#include "content/common/browser_plugin/browser_plugin_constants.h"
#include "content/renderer/browser_plugin/browser_plugin.h"
#include "third_party/WebKit/public/web/WebBindings.h"
#include "third_party/npapi/bindings/npapi.h"
using blink::WebBindings;
namespace content {
namespace {
BrowserPluginBindings* GetBindings(NPObject* object) {
return static_cast<BrowserPluginBindings::BrowserPluginNPObject*>(object)->
message_channel.get();
}
std::string StringFromNPVariant(const NPVariant& variant) {
if (!NPVARIANT_IS_STRING(variant))
return std::string();
const NPString& np_string = NPVARIANT_TO_STRING(variant);
return std::string(np_string.UTF8Characters, np_string.UTF8Length);
}
//------------------------------------------------------------------------------
// Implementations of NPClass functions. These are here to:
// - Implement src attribute.
//------------------------------------------------------------------------------
NPObject* BrowserPluginBindingsAllocate(NPP npp, NPClass* the_class) {
return new BrowserPluginBindings::BrowserPluginNPObject;
}
void BrowserPluginBindingsDeallocate(NPObject* object) {
BrowserPluginBindings::BrowserPluginNPObject* instance =
static_cast<BrowserPluginBindings::BrowserPluginNPObject*>(object);
delete instance;
}
bool BrowserPluginBindingsHasMethod(NPObject* np_obj, NPIdentifier name) {
return false;
}
bool BrowserPluginBindingsInvokeDefault(NPObject* np_obj,
const NPVariant* args,
uint32 arg_count,
NPVariant* result) {
NOTIMPLEMENTED();
return false;
}
bool BrowserPluginBindingsHasProperty(NPObject* np_obj, NPIdentifier name) {
if (!np_obj)
return false;
BrowserPluginBindings* bindings = GetBindings(np_obj);
if (!bindings)
return false;
return bindings->HasProperty(name);
}
bool BrowserPluginBindingsGetProperty(NPObject* np_obj, NPIdentifier name,
NPVariant* result) {
if (!np_obj)
return false;
if (!result)
return false;
// All attributes from here on rely on the bindings, so retrieve it once and
// return on failure.
BrowserPluginBindings* bindings = GetBindings(np_obj);
if (!bindings)
return false;
return bindings->GetProperty(name, result);
}
bool BrowserPluginBindingsSetProperty(NPObject* np_obj, NPIdentifier name,
const NPVariant* variant) {
if (!np_obj)
return false;
if (!variant)
return false;
// All attributes from here on rely on the bindings, so retrieve it once and
// return on failure.
BrowserPluginBindings* bindings = GetBindings(np_obj);
if (!bindings)
return false;
if (variant->type == NPVariantType_Null)
return bindings->RemoveProperty(np_obj, name);
return bindings->SetProperty(np_obj, name, variant);
}
bool BrowserPluginBindingsEnumerate(NPObject *np_obj, NPIdentifier **value,
uint32_t *count) {
NOTIMPLEMENTED();
return true;
}
NPClass browser_plugin_message_class = {
NP_CLASS_STRUCT_VERSION,
&BrowserPluginBindingsAllocate,
&BrowserPluginBindingsDeallocate,
NULL,
&BrowserPluginBindingsHasMethod,
NULL,
&BrowserPluginBindingsInvokeDefault,
&BrowserPluginBindingsHasProperty,
&BrowserPluginBindingsGetProperty,
&BrowserPluginBindingsSetProperty,
NULL,
&BrowserPluginBindingsEnumerate,
};
} // namespace
// BrowserPluginPropertyBinding ------------------------------------------------
class BrowserPluginPropertyBinding {
public:
explicit BrowserPluginPropertyBinding(const char name[]) : name_(name) {}
virtual ~BrowserPluginPropertyBinding() {}
const std::string& name() const { return name_; }
bool MatchesName(NPIdentifier name) const {
return WebBindings::getStringIdentifier(name_.c_str()) == name;
}
virtual bool GetProperty(BrowserPluginBindings* bindings,
NPVariant* result) = 0;
virtual bool SetProperty(BrowserPluginBindings* bindings,
NPObject* np_obj,
const NPVariant* variant) = 0;
virtual void RemoveProperty(BrowserPluginBindings* bindings,
NPObject* np_obj) = 0;
// Updates the DOM Attribute value with the current property value.
void UpdateDOMAttribute(BrowserPluginBindings* bindings,
std::string new_value) {
bindings->instance()->UpdateDOMAttribute(name(), new_value);
}
private:
std::string name_;
DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBinding);
};
class BrowserPluginPropertyBindingAllowTransparency
: public BrowserPluginPropertyBinding {
public:
BrowserPluginPropertyBindingAllowTransparency()
: BrowserPluginPropertyBinding(
browser_plugin::kAttributeAllowTransparency) {
}
virtual bool GetProperty(BrowserPluginBindings* bindings,
NPVariant* result) OVERRIDE {
bool allow_transparency =
bindings->instance()->GetAllowTransparencyAttribute();
BOOLEAN_TO_NPVARIANT(allow_transparency, *result);
return true;
}
virtual bool SetProperty(BrowserPluginBindings* bindings,
NPObject* np_obj,
const NPVariant* variant) OVERRIDE {
std::string value = StringFromNPVariant(*variant);
if (!bindings->instance()->HasDOMAttribute(name())) {
UpdateDOMAttribute(bindings, value);
bindings->instance()->ParseAllowTransparencyAttribute();
} else {
UpdateDOMAttribute(bindings, value);
}
return true;
}
virtual void RemoveProperty(BrowserPluginBindings* bindings,
NPObject* np_obj) OVERRIDE {
bindings->instance()->RemoveDOMAttribute(name());
bindings->instance()->ParseAllowTransparencyAttribute();
}
private:
DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingAllowTransparency);
};
// BrowserPluginBindings ------------------------------------------------------
BrowserPluginBindings::BrowserPluginNPObject::BrowserPluginNPObject() {
}
BrowserPluginBindings::BrowserPluginNPObject::~BrowserPluginNPObject() {
}
BrowserPluginBindings::BrowserPluginBindings(BrowserPlugin* instance)
: instance_(instance),
np_object_(NULL),
weak_ptr_factory_(this) {
NPObject* obj =
WebBindings::createObject(instance->pluginNPP(),
&browser_plugin_message_class);
np_object_ = static_cast<BrowserPluginBindings::BrowserPluginNPObject*>(obj);
np_object_->message_channel = weak_ptr_factory_.GetWeakPtr();
property_bindings_.push_back(
new BrowserPluginPropertyBindingAllowTransparency);
}
BrowserPluginBindings::~BrowserPluginBindings() {
WebBindings::releaseObject(np_object_);
}
bool BrowserPluginBindings::HasProperty(NPIdentifier name) const {
for (PropertyBindingList::const_iterator iter = property_bindings_.begin();
iter != property_bindings_.end();
++iter) {
if ((*iter)->MatchesName(name))
return true;
}
return false;
}
bool BrowserPluginBindings::SetProperty(NPObject* np_obj,
NPIdentifier name,
const NPVariant* variant) {
for (PropertyBindingList::iterator iter = property_bindings_.begin();
iter != property_bindings_.end();
++iter) {
if ((*iter)->MatchesName(name)) {
if ((*iter)->SetProperty(this, np_obj, variant)) {
return true;
}
break;
}
}
return false;
}
bool BrowserPluginBindings::RemoveProperty(NPObject* np_obj,
NPIdentifier name) {
for (PropertyBindingList::iterator iter = property_bindings_.begin();
iter != property_bindings_.end();
++iter) {
if ((*iter)->MatchesName(name)) {
(*iter)->RemoveProperty(this, np_obj);
return true;
}
}
return false;
}
bool BrowserPluginBindings::GetProperty(NPIdentifier name, NPVariant* result) {
for (PropertyBindingList::iterator iter = property_bindings_.begin();
iter != property_bindings_.end();
++iter) {
if ((*iter)->MatchesName(name))
return (*iter)->GetProperty(this, result);
}
return false;
}
} // namespace content