1 // Copyright (c) 2012 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.
5 #include "content/renderer/browser_plugin/browser_plugin_bindings.h"
10 #include "base/bind.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/strings/string16.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/string_split.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "content/common/browser_plugin/browser_plugin_constants.h"
17 #include "content/public/renderer/v8_value_converter.h"
18 #include "content/renderer/browser_plugin/browser_plugin.h"
19 #include "third_party/WebKit/public/platform/WebString.h"
20 #include "third_party/WebKit/public/web/WebBindings.h"
21 #include "third_party/WebKit/public/web/WebDOMMessageEvent.h"
22 #include "third_party/WebKit/public/web/WebDocument.h"
23 #include "third_party/WebKit/public/web/WebElement.h"
24 #include "third_party/WebKit/public/web/WebFrame.h"
25 #include "third_party/WebKit/public/web/WebNode.h"
26 #include "third_party/WebKit/public/web/WebPluginContainer.h"
27 #include "third_party/WebKit/public/web/WebView.h"
28 #include "third_party/npapi/bindings/npapi.h"
29 #include "v8/include/v8.h"
31 using blink::WebBindings;
32 using blink::WebElement;
33 using blink::WebDOMEvent;
34 using blink::WebDOMMessageEvent;
35 using blink::WebPluginContainer;
36 using blink::WebString;
42 BrowserPluginBindings* GetBindings(NPObject* object) {
43 return static_cast<BrowserPluginBindings::BrowserPluginNPObject*>(object)->
44 message_channel.get();
47 std::string StringFromNPVariant(const NPVariant& variant) {
48 if (!NPVARIANT_IS_STRING(variant))
50 const NPString& np_string = NPVARIANT_TO_STRING(variant);
51 return std::string(np_string.UTF8Characters, np_string.UTF8Length);
54 // Depending on where the attribute comes from it could be a string, int32,
55 // or a double. Javascript tends to produce an int32 or a string, but setting
56 // the value from the developer tools console may also produce a double.
57 int IntFromNPVariant(const NPVariant& variant) {
59 switch (variant.type) {
60 case NPVariantType_Double:
61 value = NPVARIANT_TO_DOUBLE(variant);
63 case NPVariantType_Int32:
64 value = NPVARIANT_TO_INT32(variant);
66 case NPVariantType_String:
67 base::StringToInt(StringFromNPVariant(variant), &value);
75 //------------------------------------------------------------------------------
76 // Implementations of NPClass functions. These are here to:
77 // - Implement src attribute.
78 //------------------------------------------------------------------------------
79 NPObject* BrowserPluginBindingsAllocate(NPP npp, NPClass* the_class) {
80 return new BrowserPluginBindings::BrowserPluginNPObject;
83 void BrowserPluginBindingsDeallocate(NPObject* object) {
84 BrowserPluginBindings::BrowserPluginNPObject* instance =
85 static_cast<BrowserPluginBindings::BrowserPluginNPObject*>(object);
89 bool BrowserPluginBindingsHasMethod(NPObject* np_obj, NPIdentifier name) {
93 BrowserPluginBindings* bindings = GetBindings(np_obj);
97 return bindings->HasMethod(name);
100 bool BrowserPluginBindingsInvoke(NPObject* np_obj, NPIdentifier name,
101 const NPVariant* args, uint32 arg_count,
106 BrowserPluginBindings* bindings = GetBindings(np_obj);
110 return bindings->InvokeMethod(name, args, arg_count, result);
113 bool BrowserPluginBindingsInvokeDefault(NPObject* np_obj,
114 const NPVariant* args,
121 bool BrowserPluginBindingsHasProperty(NPObject* np_obj, NPIdentifier name) {
125 BrowserPluginBindings* bindings = GetBindings(np_obj);
129 return bindings->HasProperty(name);
132 bool BrowserPluginBindingsGetProperty(NPObject* np_obj, NPIdentifier name,
140 // All attributes from here on rely on the bindings, so retrieve it once and
141 // return on failure.
142 BrowserPluginBindings* bindings = GetBindings(np_obj);
146 return bindings->GetProperty(name, result);
149 bool BrowserPluginBindingsSetProperty(NPObject* np_obj, NPIdentifier name,
150 const NPVariant* variant) {
156 // All attributes from here on rely on the bindings, so retrieve it once and
157 // return on failure.
158 BrowserPluginBindings* bindings = GetBindings(np_obj);
162 if (variant->type == NPVariantType_Null)
163 return bindings->RemoveProperty(np_obj, name);
165 return bindings->SetProperty(np_obj, name, variant);
168 bool BrowserPluginBindingsEnumerate(NPObject *np_obj, NPIdentifier **value,
174 NPClass browser_plugin_message_class = {
175 NP_CLASS_STRUCT_VERSION,
176 &BrowserPluginBindingsAllocate,
177 &BrowserPluginBindingsDeallocate,
179 &BrowserPluginBindingsHasMethod,
180 &BrowserPluginBindingsInvoke,
181 &BrowserPluginBindingsInvokeDefault,
182 &BrowserPluginBindingsHasProperty,
183 &BrowserPluginBindingsGetProperty,
184 &BrowserPluginBindingsSetProperty,
186 &BrowserPluginBindingsEnumerate,
191 // BrowserPluginMethodBinding --------------------------------------------------
193 class BrowserPluginMethodBinding {
195 BrowserPluginMethodBinding(const char name[], uint32 arg_count)
197 arg_count_(arg_count) {
200 virtual ~BrowserPluginMethodBinding() {}
202 bool MatchesName(NPIdentifier name) const {
203 return WebBindings::getStringIdentifier(name_.c_str()) == name;
206 uint32 arg_count() const { return arg_count_; }
208 virtual bool Invoke(BrowserPluginBindings* bindings,
209 const NPVariant* args,
210 NPVariant* result) = 0;
216 DISALLOW_COPY_AND_ASSIGN(BrowserPluginMethodBinding);
219 class BrowserPluginBindingAttach: public BrowserPluginMethodBinding {
221 BrowserPluginBindingAttach()
222 : BrowserPluginMethodBinding(browser_plugin::kMethodInternalAttach, 2) {}
224 virtual bool Invoke(BrowserPluginBindings* bindings,
225 const NPVariant* args,
226 NPVariant* result) OVERRIDE {
227 bool attached = InvokeHelper(bindings, args);
228 BOOLEAN_TO_NPVARIANT(attached, *result);
233 bool InvokeHelper(BrowserPluginBindings* bindings, const NPVariant* args) {
234 if (!bindings->instance()->render_view())
237 int instance_id = IntFromNPVariant(args[0]);
241 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
242 v8::Handle<v8::Value> obj(blink::WebBindings::toV8Value(&args[1]));
243 scoped_ptr<base::Value> value(
244 converter->FromV8Value(obj, bindings->instance()->render_view()->
245 GetWebView()->mainFrame()->mainWorldScriptContext()));
249 if (!value->IsType(base::Value::TYPE_DICTIONARY))
252 scoped_ptr<base::DictionaryValue> extra_params(
253 static_cast<base::DictionaryValue*>(value.release()));
254 bindings->instance()->Attach(instance_id, extra_params.Pass());
257 DISALLOW_COPY_AND_ASSIGN(BrowserPluginBindingAttach);
260 // BrowserPluginPropertyBinding ------------------------------------------------
262 class BrowserPluginPropertyBinding {
264 explicit BrowserPluginPropertyBinding(const char name[]) : name_(name) {}
265 virtual ~BrowserPluginPropertyBinding() {}
266 const std::string& name() const { return name_; }
267 bool MatchesName(NPIdentifier name) const {
268 return WebBindings::getStringIdentifier(name_.c_str()) == name;
270 virtual bool GetProperty(BrowserPluginBindings* bindings,
271 NPVariant* result) = 0;
272 virtual bool SetProperty(BrowserPluginBindings* bindings,
274 const NPVariant* variant) = 0;
275 virtual void RemoveProperty(BrowserPluginBindings* bindings,
276 NPObject* np_obj) = 0;
277 // Updates the DOM Attribute value with the current property value.
278 void UpdateDOMAttribute(BrowserPluginBindings* bindings,
279 std::string new_value) {
280 bindings->instance()->UpdateDOMAttribute(name(), new_value);
285 DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBinding);
288 class BrowserPluginPropertyBindingAllowTransparency
289 : public BrowserPluginPropertyBinding {
291 BrowserPluginPropertyBindingAllowTransparency()
292 : BrowserPluginPropertyBinding(
293 browser_plugin::kAttributeAllowTransparency) {
295 virtual bool GetProperty(BrowserPluginBindings* bindings,
296 NPVariant* result) OVERRIDE {
297 bool allow_transparency =
298 bindings->instance()->GetAllowTransparencyAttribute();
299 BOOLEAN_TO_NPVARIANT(allow_transparency, *result);
302 virtual bool SetProperty(BrowserPluginBindings* bindings,
304 const NPVariant* variant) OVERRIDE {
305 std::string value = StringFromNPVariant(*variant);
306 if (!bindings->instance()->HasDOMAttribute(name())) {
307 UpdateDOMAttribute(bindings, value);
308 bindings->instance()->ParseAllowTransparencyAttribute();
310 UpdateDOMAttribute(bindings, value);
314 virtual void RemoveProperty(BrowserPluginBindings* bindings,
315 NPObject* np_obj) OVERRIDE {
316 bindings->instance()->RemoveDOMAttribute(name());
317 bindings->instance()->ParseAllowTransparencyAttribute();
320 DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingAllowTransparency);
323 class BrowserPluginPropertyBindingContentWindow
324 : public BrowserPluginPropertyBinding {
326 BrowserPluginPropertyBindingContentWindow()
327 : BrowserPluginPropertyBinding(browser_plugin::kAttributeContentWindow) {
329 virtual bool GetProperty(BrowserPluginBindings* bindings,
330 NPVariant* result) OVERRIDE {
331 NPObject* obj = bindings->instance()->GetContentWindow();
333 result->type = NPVariantType_Object;
334 result->value.objectValue = WebBindings::retainObject(obj);
338 virtual bool SetProperty(BrowserPluginBindings* bindings,
340 const NPVariant* variant) OVERRIDE {
343 virtual void RemoveProperty(BrowserPluginBindings* bindings,
344 NPObject* np_obj) OVERRIDE {}
346 DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingContentWindow);
350 // BrowserPluginBindings ------------------------------------------------------
352 BrowserPluginBindings::BrowserPluginNPObject::BrowserPluginNPObject() {
355 BrowserPluginBindings::BrowserPluginNPObject::~BrowserPluginNPObject() {
358 BrowserPluginBindings::BrowserPluginBindings(BrowserPlugin* instance)
359 : instance_(instance),
361 weak_ptr_factory_(this) {
363 WebBindings::createObject(instance->pluginNPP(),
364 &browser_plugin_message_class);
365 np_object_ = static_cast<BrowserPluginBindings::BrowserPluginNPObject*>(obj);
366 np_object_->message_channel = weak_ptr_factory_.GetWeakPtr();
368 method_bindings_.push_back(new BrowserPluginBindingAttach);
370 property_bindings_.push_back(
371 new BrowserPluginPropertyBindingAllowTransparency);
372 property_bindings_.push_back(new BrowserPluginPropertyBindingContentWindow);
375 BrowserPluginBindings::~BrowserPluginBindings() {
376 WebBindings::releaseObject(np_object_);
379 bool BrowserPluginBindings::HasMethod(NPIdentifier name) const {
380 for (BindingList::const_iterator iter = method_bindings_.begin();
381 iter != method_bindings_.end();
383 if ((*iter)->MatchesName(name))
389 bool BrowserPluginBindings::InvokeMethod(NPIdentifier name,
390 const NPVariant* args,
393 for (BindingList::iterator iter = method_bindings_.begin();
394 iter != method_bindings_.end();
396 if ((*iter)->MatchesName(name) && (*iter)->arg_count() == arg_count)
397 return (*iter)->Invoke(this, args, result);
402 bool BrowserPluginBindings::HasProperty(NPIdentifier name) const {
403 for (PropertyBindingList::const_iterator iter = property_bindings_.begin();
404 iter != property_bindings_.end();
406 if ((*iter)->MatchesName(name))
412 bool BrowserPluginBindings::SetProperty(NPObject* np_obj,
414 const NPVariant* variant) {
415 for (PropertyBindingList::iterator iter = property_bindings_.begin();
416 iter != property_bindings_.end();
418 if ((*iter)->MatchesName(name)) {
419 if ((*iter)->SetProperty(this, np_obj, variant)) {
428 bool BrowserPluginBindings::RemoveProperty(NPObject* np_obj,
430 for (PropertyBindingList::iterator iter = property_bindings_.begin();
431 iter != property_bindings_.end();
433 if ((*iter)->MatchesName(name)) {
434 (*iter)->RemoveProperty(this, np_obj);
441 bool BrowserPluginBindings::GetProperty(NPIdentifier name, NPVariant* result) {
442 for (PropertyBindingList::iterator iter = property_bindings_.begin();
443 iter != property_bindings_.end();
445 if ((*iter)->MatchesName(name))
446 return (*iter)->GetProperty(this, result);
451 } // namespace content