• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "content/renderer/browser_plugin/browser_plugin_bindings.h"
6 
7 #include <cstdlib>
8 #include <string>
9 
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"
30 
31 using blink::WebBindings;
32 using blink::WebElement;
33 using blink::WebDOMEvent;
34 using blink::WebDOMMessageEvent;
35 using blink::WebPluginContainer;
36 using blink::WebString;
37 
38 namespace content {
39 
40 namespace {
41 
GetBindings(NPObject * object)42 BrowserPluginBindings* GetBindings(NPObject* object) {
43   return static_cast<BrowserPluginBindings::BrowserPluginNPObject*>(object)->
44       message_channel.get();
45 }
46 
StringFromNPVariant(const NPVariant & variant)47 std::string StringFromNPVariant(const NPVariant& variant) {
48   if (!NPVARIANT_IS_STRING(variant))
49     return std::string();
50   const NPString& np_string = NPVARIANT_TO_STRING(variant);
51   return std::string(np_string.UTF8Characters, np_string.UTF8Length);
52 }
53 
StringToNPVariant(const std::string & in,NPVariant * variant)54 bool StringToNPVariant(const std::string &in, NPVariant *variant) {
55   size_t length = in.size();
56   NPUTF8 *chars = static_cast<NPUTF8 *>(malloc(length));
57   if (!chars) {
58     VOID_TO_NPVARIANT(*variant);
59     return false;
60   }
61   memcpy(chars, in.c_str(), length);
62   STRINGN_TO_NPVARIANT(chars, length, *variant);
63   return true;
64 }
65 
66 // Depending on where the attribute comes from it could be a string, int32,
67 // or a double. Javascript tends to produce an int32 or a string, but setting
68 // the value from the developer tools console may also produce a double.
IntFromNPVariant(const NPVariant & variant)69 int IntFromNPVariant(const NPVariant& variant) {
70   int value = 0;
71   switch (variant.type) {
72     case NPVariantType_Double:
73       value = NPVARIANT_TO_DOUBLE(variant);
74       break;
75     case NPVariantType_Int32:
76       value = NPVARIANT_TO_INT32(variant);
77       break;
78     case NPVariantType_String:
79       base::StringToInt(StringFromNPVariant(variant), &value);
80       break;
81     default:
82       break;
83   }
84   return value;
85 }
86 
87 //------------------------------------------------------------------------------
88 // Implementations of NPClass functions.  These are here to:
89 // - Implement src attribute.
90 //------------------------------------------------------------------------------
BrowserPluginBindingsAllocate(NPP npp,NPClass * the_class)91 NPObject* BrowserPluginBindingsAllocate(NPP npp, NPClass* the_class) {
92   return new BrowserPluginBindings::BrowserPluginNPObject;
93 }
94 
BrowserPluginBindingsDeallocate(NPObject * object)95 void BrowserPluginBindingsDeallocate(NPObject* object) {
96   BrowserPluginBindings::BrowserPluginNPObject* instance =
97       static_cast<BrowserPluginBindings::BrowserPluginNPObject*>(object);
98   delete instance;
99 }
100 
BrowserPluginBindingsHasMethod(NPObject * np_obj,NPIdentifier name)101 bool BrowserPluginBindingsHasMethod(NPObject* np_obj, NPIdentifier name) {
102   if (!np_obj)
103     return false;
104 
105   BrowserPluginBindings* bindings = GetBindings(np_obj);
106   if (!bindings)
107     return false;
108 
109   return bindings->HasMethod(name);
110 }
111 
BrowserPluginBindingsInvoke(NPObject * np_obj,NPIdentifier name,const NPVariant * args,uint32 arg_count,NPVariant * result)112 bool BrowserPluginBindingsInvoke(NPObject* np_obj, NPIdentifier name,
113                                  const NPVariant* args, uint32 arg_count,
114                                  NPVariant* result) {
115   if (!np_obj)
116     return false;
117 
118   BrowserPluginBindings* bindings = GetBindings(np_obj);
119   if (!bindings)
120     return false;
121 
122   return bindings->InvokeMethod(name, args, arg_count, result);
123 }
124 
BrowserPluginBindingsInvokeDefault(NPObject * np_obj,const NPVariant * args,uint32 arg_count,NPVariant * result)125 bool BrowserPluginBindingsInvokeDefault(NPObject* np_obj,
126                                         const NPVariant* args,
127                                         uint32 arg_count,
128                                         NPVariant* result) {
129   NOTIMPLEMENTED();
130   return false;
131 }
132 
BrowserPluginBindingsHasProperty(NPObject * np_obj,NPIdentifier name)133 bool BrowserPluginBindingsHasProperty(NPObject* np_obj, NPIdentifier name) {
134   if (!np_obj)
135     return false;
136 
137   BrowserPluginBindings* bindings = GetBindings(np_obj);
138   if (!bindings)
139     return false;
140 
141   return bindings->HasProperty(name);
142 }
143 
BrowserPluginBindingsGetProperty(NPObject * np_obj,NPIdentifier name,NPVariant * result)144 bool BrowserPluginBindingsGetProperty(NPObject* np_obj, NPIdentifier name,
145                                       NPVariant* result) {
146   if (!np_obj)
147     return false;
148 
149   if (!result)
150     return false;
151 
152   // All attributes from here on rely on the bindings, so retrieve it once and
153   // return on failure.
154   BrowserPluginBindings* bindings = GetBindings(np_obj);
155   if (!bindings)
156     return false;
157 
158   return bindings->GetProperty(name, result);
159 }
160 
BrowserPluginBindingsSetProperty(NPObject * np_obj,NPIdentifier name,const NPVariant * variant)161 bool BrowserPluginBindingsSetProperty(NPObject* np_obj, NPIdentifier name,
162                                       const NPVariant* variant) {
163   if (!np_obj)
164     return false;
165   if (!variant)
166     return false;
167 
168   // All attributes from here on rely on the bindings, so retrieve it once and
169   // return on failure.
170   BrowserPluginBindings* bindings = GetBindings(np_obj);
171   if (!bindings)
172     return false;
173 
174   if (variant->type == NPVariantType_Null)
175     return bindings->RemoveProperty(np_obj, name);
176 
177   return bindings->SetProperty(np_obj, name, variant);
178 }
179 
BrowserPluginBindingsEnumerate(NPObject * np_obj,NPIdentifier ** value,uint32_t * count)180 bool BrowserPluginBindingsEnumerate(NPObject *np_obj, NPIdentifier **value,
181                                     uint32_t *count) {
182   NOTIMPLEMENTED();
183   return true;
184 }
185 
186 NPClass browser_plugin_message_class = {
187   NP_CLASS_STRUCT_VERSION,
188   &BrowserPluginBindingsAllocate,
189   &BrowserPluginBindingsDeallocate,
190   NULL,
191   &BrowserPluginBindingsHasMethod,
192   &BrowserPluginBindingsInvoke,
193   &BrowserPluginBindingsInvokeDefault,
194   &BrowserPluginBindingsHasProperty,
195   &BrowserPluginBindingsGetProperty,
196   &BrowserPluginBindingsSetProperty,
197   NULL,
198   &BrowserPluginBindingsEnumerate,
199 };
200 
201 }  // namespace
202 
203 // BrowserPluginMethodBinding --------------------------------------------------
204 
205 class BrowserPluginMethodBinding {
206  public:
BrowserPluginMethodBinding(const char name[],uint32 arg_count)207   BrowserPluginMethodBinding(const char name[], uint32 arg_count)
208       : name_(name),
209         arg_count_(arg_count) {
210   }
211 
~BrowserPluginMethodBinding()212   virtual ~BrowserPluginMethodBinding() {}
213 
MatchesName(NPIdentifier name) const214   bool MatchesName(NPIdentifier name) const {
215     return WebBindings::getStringIdentifier(name_.c_str()) == name;
216   }
217 
arg_count() const218   uint32 arg_count() const { return arg_count_; }
219 
220   virtual bool Invoke(BrowserPluginBindings* bindings,
221                       const NPVariant* args,
222                       NPVariant* result) = 0;
223 
224  private:
225   std::string name_;
226   uint32 arg_count_;
227 
228   DISALLOW_COPY_AND_ASSIGN(BrowserPluginMethodBinding);
229 };
230 
231 class BrowserPluginBindingAttach: public BrowserPluginMethodBinding {
232  public:
BrowserPluginBindingAttach()233   BrowserPluginBindingAttach()
234       : BrowserPluginMethodBinding(
235           browser_plugin::kMethodInternalAttach, 1) {
236   }
237 
Invoke(BrowserPluginBindings * bindings,const NPVariant * args,NPVariant * result)238   virtual bool Invoke(BrowserPluginBindings* bindings,
239                       const NPVariant* args,
240                       NPVariant* result) OVERRIDE {
241     if (!bindings->instance()->render_view())
242       return false;
243 
244     scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
245     v8::Handle<v8::Value> obj(blink::WebBindings::toV8Value(&args[0]));
246     scoped_ptr<base::Value> value(
247         converter->FromV8Value(obj, bindings->instance()->render_view()->
248             GetWebView()->mainFrame()->mainWorldScriptContext()));
249     if (!value)
250       return false;
251 
252     if (!value->IsType(Value::TYPE_DICTIONARY))
253       return false;
254 
255     scoped_ptr<base::DictionaryValue> extra_params(
256         static_cast<base::DictionaryValue*>(value.release()));
257     bindings->instance()->Attach(extra_params.Pass());
258     return true;
259   }
260 
261  private:
262   DISALLOW_COPY_AND_ASSIGN(BrowserPluginBindingAttach);
263 };
264 
265 class BrowserPluginBindingAttachWindowTo : public BrowserPluginMethodBinding {
266  public:
BrowserPluginBindingAttachWindowTo()267   BrowserPluginBindingAttachWindowTo()
268       : BrowserPluginMethodBinding(
269           browser_plugin::kMethodInternalAttachWindowTo, 2) {
270   }
271 
Invoke(BrowserPluginBindings * bindings,const NPVariant * args,NPVariant * result)272   virtual bool Invoke(BrowserPluginBindings* bindings,
273                       const NPVariant* args,
274                       NPVariant* result) OVERRIDE {
275     blink::WebNode node;
276     WebBindings::getNode(NPVARIANT_TO_OBJECT(args[0]), &node);
277     int window_id = IntFromNPVariant(args[1]);
278     BOOLEAN_TO_NPVARIANT(BrowserPlugin::AttachWindowTo(node, window_id),
279                          *result);
280     return true;
281   }
282 
283  private:
284   DISALLOW_COPY_AND_ASSIGN(BrowserPluginBindingAttachWindowTo);
285 };
286 
287 // BrowserPluginPropertyBinding ------------------------------------------------
288 
289 class BrowserPluginPropertyBinding {
290  public:
BrowserPluginPropertyBinding(const char name[])291   explicit BrowserPluginPropertyBinding(const char name[]) : name_(name) {}
~BrowserPluginPropertyBinding()292   virtual ~BrowserPluginPropertyBinding() {}
name() const293   const std::string& name() const { return name_; }
MatchesName(NPIdentifier name) const294   bool MatchesName(NPIdentifier name) const {
295     return WebBindings::getStringIdentifier(name_.c_str()) == name;
296   }
297   virtual bool GetProperty(BrowserPluginBindings* bindings,
298                            NPVariant* result) = 0;
299   virtual bool SetProperty(BrowserPluginBindings* bindings,
300                            NPObject* np_obj,
301                            const NPVariant* variant) = 0;
302   virtual void RemoveProperty(BrowserPluginBindings* bindings,
303                               NPObject* np_obj) = 0;
304   // Updates the DOM Attribute value with the current property value.
UpdateDOMAttribute(BrowserPluginBindings * bindings,std::string new_value)305   void UpdateDOMAttribute(BrowserPluginBindings* bindings,
306                           std::string new_value) {
307     bindings->instance()->UpdateDOMAttribute(name(), new_value);
308   }
309  private:
310   std::string name_;
311 
312   DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBinding);
313 };
314 
315 class BrowserPluginPropertyBindingAllowTransparency
316     : public BrowserPluginPropertyBinding {
317  public:
BrowserPluginPropertyBindingAllowTransparency()318   BrowserPluginPropertyBindingAllowTransparency()
319       : BrowserPluginPropertyBinding(
320           browser_plugin::kAttributeAllowTransparency) {
321   }
GetProperty(BrowserPluginBindings * bindings,NPVariant * result)322   virtual bool GetProperty(BrowserPluginBindings* bindings,
323                            NPVariant* result) OVERRIDE {
324     bool allow_transparency =
325         bindings->instance()->GetAllowTransparencyAttribute();
326     BOOLEAN_TO_NPVARIANT(allow_transparency, *result);
327     return true;
328   }
SetProperty(BrowserPluginBindings * bindings,NPObject * np_obj,const NPVariant * variant)329   virtual bool SetProperty(BrowserPluginBindings* bindings,
330                            NPObject* np_obj,
331                            const NPVariant* variant) OVERRIDE {
332     std::string value = StringFromNPVariant(*variant);
333     if (!bindings->instance()->HasDOMAttribute(name())) {
334       UpdateDOMAttribute(bindings, value);
335       bindings->instance()->ParseAllowTransparencyAttribute();
336     } else {
337       UpdateDOMAttribute(bindings, value);
338     }
339     return true;
340   }
RemoveProperty(BrowserPluginBindings * bindings,NPObject * np_obj)341   virtual void RemoveProperty(BrowserPluginBindings* bindings,
342                               NPObject* np_obj) OVERRIDE {
343     bindings->instance()->RemoveDOMAttribute(name());
344     bindings->instance()->ParseAllowTransparencyAttribute();
345   }
346  private:
347   DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingAllowTransparency);
348 };
349 
350 class BrowserPluginPropertyBindingAutoSize
351     : public BrowserPluginPropertyBinding {
352  public:
BrowserPluginPropertyBindingAutoSize()353   BrowserPluginPropertyBindingAutoSize()
354       : BrowserPluginPropertyBinding(browser_plugin::kAttributeAutoSize) {
355   }
GetProperty(BrowserPluginBindings * bindings,NPVariant * result)356   virtual bool GetProperty(BrowserPluginBindings* bindings,
357                            NPVariant* result) OVERRIDE {
358     bool auto_size = bindings->instance()->GetAutoSizeAttribute();
359     BOOLEAN_TO_NPVARIANT(auto_size, *result);
360     return true;
361   }
SetProperty(BrowserPluginBindings * bindings,NPObject * np_obj,const NPVariant * variant)362   virtual bool SetProperty(BrowserPluginBindings* bindings,
363                            NPObject* np_obj,
364                            const NPVariant* variant) OVERRIDE {
365     std::string value = StringFromNPVariant(*variant);
366     if (!bindings->instance()->HasDOMAttribute(name())) {
367       UpdateDOMAttribute(bindings, value);
368       bindings->instance()->ParseAutoSizeAttribute();
369     } else {
370       UpdateDOMAttribute(bindings, value);
371     }
372     return true;
373   }
RemoveProperty(BrowserPluginBindings * bindings,NPObject * np_obj)374   virtual void RemoveProperty(BrowserPluginBindings* bindings,
375                               NPObject* np_obj) OVERRIDE {
376     bindings->instance()->RemoveDOMAttribute(name());
377     bindings->instance()->ParseAutoSizeAttribute();
378   }
379  private:
380   DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingAutoSize);
381 };
382 
383 class BrowserPluginPropertyBindingContentWindow
384     : public BrowserPluginPropertyBinding {
385  public:
BrowserPluginPropertyBindingContentWindow()386   BrowserPluginPropertyBindingContentWindow()
387       : BrowserPluginPropertyBinding(browser_plugin::kAttributeContentWindow) {
388   }
GetProperty(BrowserPluginBindings * bindings,NPVariant * result)389   virtual bool GetProperty(BrowserPluginBindings* bindings,
390                            NPVariant* result) OVERRIDE {
391     NPObject* obj = bindings->instance()->GetContentWindow();
392     if (obj) {
393       result->type = NPVariantType_Object;
394       result->value.objectValue = WebBindings::retainObject(obj);
395     }
396     return true;
397   }
SetProperty(BrowserPluginBindings * bindings,NPObject * np_obj,const NPVariant * variant)398   virtual bool SetProperty(BrowserPluginBindings* bindings,
399                            NPObject* np_obj,
400                            const NPVariant* variant) OVERRIDE {
401     return false;
402   }
RemoveProperty(BrowserPluginBindings * bindings,NPObject * np_obj)403   virtual void RemoveProperty(BrowserPluginBindings* bindings,
404                               NPObject* np_obj) OVERRIDE {}
405  private:
406   DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingContentWindow);
407 };
408 
409 class BrowserPluginPropertyBindingMaxHeight
410     : public BrowserPluginPropertyBinding {
411  public:
BrowserPluginPropertyBindingMaxHeight()412   BrowserPluginPropertyBindingMaxHeight()
413       : BrowserPluginPropertyBinding(browser_plugin::kAttributeMaxHeight) {
414   }
GetProperty(BrowserPluginBindings * bindings,NPVariant * result)415   virtual bool GetProperty(BrowserPluginBindings* bindings,
416                            NPVariant* result) OVERRIDE {
417     int max_height = bindings->instance()->GetMaxHeightAttribute();
418     INT32_TO_NPVARIANT(max_height, *result);
419     return true;
420   }
SetProperty(BrowserPluginBindings * bindings,NPObject * np_obj,const NPVariant * variant)421   virtual bool SetProperty(BrowserPluginBindings* bindings,
422                            NPObject* np_obj,
423                            const NPVariant* variant) OVERRIDE {
424     int new_value = IntFromNPVariant(*variant);
425     if (bindings->instance()->GetMaxHeightAttribute() != new_value) {
426       UpdateDOMAttribute(bindings, base::IntToString(new_value));
427       bindings->instance()->ParseSizeContraintsChanged();
428     }
429     return true;
430   }
RemoveProperty(BrowserPluginBindings * bindings,NPObject * np_obj)431   virtual void RemoveProperty(BrowserPluginBindings* bindings,
432                               NPObject* np_obj) OVERRIDE {
433     bindings->instance()->RemoveDOMAttribute(name());
434     bindings->instance()->ParseSizeContraintsChanged();
435   }
436  private:
437   DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingMaxHeight);
438 };
439 
440 class BrowserPluginPropertyBindingMaxWidth
441     : public BrowserPluginPropertyBinding {
442  public:
BrowserPluginPropertyBindingMaxWidth()443   BrowserPluginPropertyBindingMaxWidth()
444       : BrowserPluginPropertyBinding(browser_plugin::kAttributeMaxWidth) {
445   }
GetProperty(BrowserPluginBindings * bindings,NPVariant * result)446   virtual bool GetProperty(BrowserPluginBindings* bindings,
447                            NPVariant* result) OVERRIDE {
448     int max_width = bindings->instance()->GetMaxWidthAttribute();
449     INT32_TO_NPVARIANT(max_width, *result);
450     return true;
451   }
SetProperty(BrowserPluginBindings * bindings,NPObject * np_obj,const NPVariant * variant)452   virtual bool SetProperty(BrowserPluginBindings* bindings,
453                            NPObject* np_obj,
454                            const NPVariant* variant) OVERRIDE {
455     int new_value = IntFromNPVariant(*variant);
456     if (bindings->instance()->GetMaxWidthAttribute() != new_value) {
457       UpdateDOMAttribute(bindings, base::IntToString(new_value));
458       bindings->instance()->ParseSizeContraintsChanged();
459     }
460     return true;
461   }
RemoveProperty(BrowserPluginBindings * bindings,NPObject * np_obj)462   virtual void RemoveProperty(BrowserPluginBindings* bindings,
463                               NPObject* np_obj) OVERRIDE {
464     bindings->instance()->RemoveDOMAttribute(name());
465     bindings->instance()->ParseSizeContraintsChanged();
466   }
467  private:
468   DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingMaxWidth);
469 };
470 
471 class BrowserPluginPropertyBindingMinHeight
472     : public BrowserPluginPropertyBinding {
473  public:
BrowserPluginPropertyBindingMinHeight()474   BrowserPluginPropertyBindingMinHeight()
475       : BrowserPluginPropertyBinding(browser_plugin::kAttributeMinHeight) {
476   }
GetProperty(BrowserPluginBindings * bindings,NPVariant * result)477   virtual bool GetProperty(BrowserPluginBindings* bindings,
478                            NPVariant* result) OVERRIDE {
479     int min_height = bindings->instance()->GetMinHeightAttribute();
480     INT32_TO_NPVARIANT(min_height, *result);
481     return true;
482   }
SetProperty(BrowserPluginBindings * bindings,NPObject * np_obj,const NPVariant * variant)483   virtual bool SetProperty(BrowserPluginBindings* bindings,
484                            NPObject* np_obj,
485                            const NPVariant* variant) OVERRIDE {
486     int new_value = IntFromNPVariant(*variant);
487     if (bindings->instance()->GetMinHeightAttribute() != new_value) {
488       UpdateDOMAttribute(bindings, base::IntToString(new_value));
489       bindings->instance()->ParseSizeContraintsChanged();
490     }
491     return true;
492   }
RemoveProperty(BrowserPluginBindings * bindings,NPObject * np_obj)493   virtual void RemoveProperty(BrowserPluginBindings* bindings,
494                               NPObject* np_obj) OVERRIDE {
495     bindings->instance()->RemoveDOMAttribute(name());
496     bindings->instance()->ParseSizeContraintsChanged();
497   }
498  private:
499   DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingMinHeight);
500 };
501 
502 class BrowserPluginPropertyBindingMinWidth
503     : public BrowserPluginPropertyBinding {
504  public:
BrowserPluginPropertyBindingMinWidth()505   BrowserPluginPropertyBindingMinWidth()
506       : BrowserPluginPropertyBinding(browser_plugin::kAttributeMinWidth) {
507   }
GetProperty(BrowserPluginBindings * bindings,NPVariant * result)508   virtual bool GetProperty(BrowserPluginBindings* bindings,
509                            NPVariant* result) OVERRIDE {
510     int min_width = bindings->instance()->GetMinWidthAttribute();
511     INT32_TO_NPVARIANT(min_width, *result);
512     return true;
513   }
SetProperty(BrowserPluginBindings * bindings,NPObject * np_obj,const NPVariant * variant)514   virtual bool SetProperty(BrowserPluginBindings* bindings,
515                            NPObject* np_obj,
516                            const NPVariant* variant) OVERRIDE {
517     int new_value = IntFromNPVariant(*variant);
518     if (bindings->instance()->GetMinWidthAttribute() != new_value) {
519       UpdateDOMAttribute(bindings, base::IntToString(new_value));
520       bindings->instance()->ParseSizeContraintsChanged();
521     }
522     return true;
523   }
RemoveProperty(BrowserPluginBindings * bindings,NPObject * np_obj)524   virtual void RemoveProperty(BrowserPluginBindings* bindings,
525                               NPObject* np_obj) OVERRIDE {
526     bindings->instance()->RemoveDOMAttribute(name());
527     bindings->instance()->ParseSizeContraintsChanged();
528   }
529  private:
530   DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingMinWidth);
531 };
532 
533 class BrowserPluginPropertyBindingName
534     : public BrowserPluginPropertyBinding {
535  public:
BrowserPluginPropertyBindingName()536   BrowserPluginPropertyBindingName()
537       : BrowserPluginPropertyBinding(browser_plugin::kAttributeName) {
538   }
GetProperty(BrowserPluginBindings * bindings,NPVariant * result)539   virtual bool GetProperty(BrowserPluginBindings* bindings,
540                            NPVariant* result) OVERRIDE {
541     std::string name = bindings->instance()->GetNameAttribute();
542     return StringToNPVariant(name, result);
543   }
SetProperty(BrowserPluginBindings * bindings,NPObject * np_obj,const NPVariant * variant)544   virtual bool SetProperty(BrowserPluginBindings* bindings,
545                            NPObject* np_obj,
546                            const NPVariant* variant) OVERRIDE {
547     std::string new_value = StringFromNPVariant(*variant);
548     if (bindings->instance()->GetNameAttribute() != new_value) {
549       UpdateDOMAttribute(bindings, new_value);
550       bindings->instance()->ParseNameAttribute();
551     }
552     return true;
553   }
RemoveProperty(BrowserPluginBindings * bindings,NPObject * np_obj)554   virtual void RemoveProperty(BrowserPluginBindings* bindings,
555                               NPObject* np_obj) OVERRIDE {
556     bindings->instance()->RemoveDOMAttribute(name());
557     bindings->instance()->ParseNameAttribute();
558   }
559  private:
560   DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingName);
561 };
562 
563 class BrowserPluginPropertyBindingPartition
564     : public BrowserPluginPropertyBinding {
565  public:
BrowserPluginPropertyBindingPartition()566   BrowserPluginPropertyBindingPartition()
567       : BrowserPluginPropertyBinding(browser_plugin::kAttributePartition) {
568   }
GetProperty(BrowserPluginBindings * bindings,NPVariant * result)569   virtual bool GetProperty(BrowserPluginBindings* bindings,
570                            NPVariant* result) OVERRIDE {
571     std::string partition_id = bindings->instance()->GetPartitionAttribute();
572     return StringToNPVariant(partition_id, result);
573   }
SetProperty(BrowserPluginBindings * bindings,NPObject * np_obj,const NPVariant * variant)574   virtual bool SetProperty(BrowserPluginBindings* bindings,
575                            NPObject* np_obj,
576                            const NPVariant* variant) OVERRIDE {
577     std::string new_value = StringFromNPVariant(*variant);
578     std::string old_value = bindings->instance()->GetPartitionAttribute();
579     if (old_value != new_value) {
580       UpdateDOMAttribute(bindings, new_value);
581       std::string error_message;
582       if (!bindings->instance()->ParsePartitionAttribute(&error_message)) {
583         // Reset to old value on error.
584         UpdateDOMAttribute(bindings, old_value);
585         // Exceptions must be set as the last operation before returning to
586         // script.
587         WebBindings::setException(
588             np_obj, static_cast<const NPUTF8 *>(error_message.c_str()));
589         return false;
590       }
591     }
592     return true;
593   }
RemoveProperty(BrowserPluginBindings * bindings,NPObject * np_obj)594   virtual void RemoveProperty(BrowserPluginBindings* bindings,
595                               NPObject* np_obj) OVERRIDE {
596     std::string error_message;
597     if (bindings->instance()->CanRemovePartitionAttribute(&error_message)) {
598       bindings->instance()->RemoveDOMAttribute(name());
599     } else {
600       WebBindings::setException(
601           np_obj, static_cast<const NPUTF8 *>(error_message.c_str()));
602     }
603   }
604  private:
605   DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingPartition);
606 };
607 
608 class BrowserPluginPropertyBindingSrc : public BrowserPluginPropertyBinding {
609  public:
BrowserPluginPropertyBindingSrc()610   BrowserPluginPropertyBindingSrc()
611       : BrowserPluginPropertyBinding(browser_plugin::kAttributeSrc) {
612   }
GetProperty(BrowserPluginBindings * bindings,NPVariant * result)613   virtual bool GetProperty(BrowserPluginBindings* bindings,
614                            NPVariant* result) OVERRIDE {
615     std::string src = bindings->instance()->GetSrcAttribute();
616     return StringToNPVariant(src, result);
617   }
SetProperty(BrowserPluginBindings * bindings,NPObject * np_obj,const NPVariant * variant)618   virtual bool SetProperty(BrowserPluginBindings* bindings,
619                            NPObject* np_obj,
620                            const NPVariant* variant) OVERRIDE {
621     std::string new_value = StringFromNPVariant(*variant);
622     // We should not be issuing navigation IPCs if we attempt to set the
623     // src property to the empty string. Instead, we want to simply restore
624     // the src attribute back to its old value.
625     if (new_value.empty()) {
626       return true;
627     }
628     std::string old_value = bindings->instance()->GetSrcAttribute();
629     // If the new value was empty then we're effectively resetting the
630     // attribute to the old value here. This will be picked up by <webview>'s
631     // mutation observer and will restore the src attribute after it has been
632     // removed.
633     UpdateDOMAttribute(bindings, new_value);
634     std::string error_message;
635     if (!bindings->instance()->ParseSrcAttribute(&error_message)) {
636       // Reset to old value on error.
637       UpdateDOMAttribute(bindings, old_value);
638       // Exceptions must be set as the last operation before returning to
639       // script.
640       WebBindings::setException(
641           np_obj, static_cast<const NPUTF8 *>(error_message.c_str()));
642       return false;
643     }
644     return true;
645   }
RemoveProperty(BrowserPluginBindings * bindings,NPObject * np_obj)646   virtual void RemoveProperty(BrowserPluginBindings* bindings,
647                               NPObject* np_obj) OVERRIDE {
648     bindings->instance()->RemoveDOMAttribute(name());
649   }
650  private:
651   DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingSrc);
652 };
653 
654 
655 // BrowserPluginBindings ------------------------------------------------------
656 
BrowserPluginNPObject()657 BrowserPluginBindings::BrowserPluginNPObject::BrowserPluginNPObject() {
658 }
659 
~BrowserPluginNPObject()660 BrowserPluginBindings::BrowserPluginNPObject::~BrowserPluginNPObject() {
661 }
662 
BrowserPluginBindings(BrowserPlugin * instance)663 BrowserPluginBindings::BrowserPluginBindings(BrowserPlugin* instance)
664     : instance_(instance),
665       np_object_(NULL),
666       weak_ptr_factory_(this) {
667   NPObject* obj =
668       WebBindings::createObject(instance->pluginNPP(),
669                                 &browser_plugin_message_class);
670   np_object_ = static_cast<BrowserPluginBindings::BrowserPluginNPObject*>(obj);
671   np_object_->message_channel = weak_ptr_factory_.GetWeakPtr();
672 
673   method_bindings_.push_back(new BrowserPluginBindingAttach);
674   method_bindings_.push_back(new BrowserPluginBindingAttachWindowTo);
675 
676   property_bindings_.push_back(
677       new BrowserPluginPropertyBindingAllowTransparency);
678   property_bindings_.push_back(new BrowserPluginPropertyBindingAutoSize);
679   property_bindings_.push_back(new BrowserPluginPropertyBindingContentWindow);
680   property_bindings_.push_back(new BrowserPluginPropertyBindingMaxHeight);
681   property_bindings_.push_back(new BrowserPluginPropertyBindingMaxWidth);
682   property_bindings_.push_back(new BrowserPluginPropertyBindingMinHeight);
683   property_bindings_.push_back(new BrowserPluginPropertyBindingMinWidth);
684   property_bindings_.push_back(new BrowserPluginPropertyBindingName);
685   property_bindings_.push_back(new BrowserPluginPropertyBindingPartition);
686   property_bindings_.push_back(new BrowserPluginPropertyBindingSrc);
687 }
688 
~BrowserPluginBindings()689 BrowserPluginBindings::~BrowserPluginBindings() {
690   WebBindings::releaseObject(np_object_);
691 }
692 
HasMethod(NPIdentifier name) const693 bool BrowserPluginBindings::HasMethod(NPIdentifier name) const {
694   for (BindingList::const_iterator iter = method_bindings_.begin();
695        iter != method_bindings_.end();
696        ++iter) {
697     if ((*iter)->MatchesName(name))
698       return true;
699   }
700   return false;
701 }
702 
InvokeMethod(NPIdentifier name,const NPVariant * args,uint32 arg_count,NPVariant * result)703 bool BrowserPluginBindings::InvokeMethod(NPIdentifier name,
704                                          const NPVariant* args,
705                                          uint32 arg_count,
706                                          NPVariant* result) {
707   for (BindingList::iterator iter = method_bindings_.begin();
708        iter != method_bindings_.end();
709        ++iter) {
710     if ((*iter)->MatchesName(name) && (*iter)->arg_count() == arg_count)
711       return (*iter)->Invoke(this, args, result);
712   }
713   return false;
714 }
715 
HasProperty(NPIdentifier name) const716 bool BrowserPluginBindings::HasProperty(NPIdentifier name) const {
717   for (PropertyBindingList::const_iterator iter = property_bindings_.begin();
718        iter != property_bindings_.end();
719        ++iter) {
720     if ((*iter)->MatchesName(name))
721       return true;
722   }
723   return false;
724 }
725 
SetProperty(NPObject * np_obj,NPIdentifier name,const NPVariant * variant)726 bool BrowserPluginBindings::SetProperty(NPObject* np_obj,
727                                         NPIdentifier name,
728                                         const NPVariant* variant) {
729   for (PropertyBindingList::iterator iter = property_bindings_.begin();
730        iter != property_bindings_.end();
731        ++iter) {
732     if ((*iter)->MatchesName(name)) {
733       if ((*iter)->SetProperty(this, np_obj, variant)) {
734         return true;
735       }
736       break;
737     }
738   }
739   return false;
740 }
741 
RemoveProperty(NPObject * np_obj,NPIdentifier name)742 bool BrowserPluginBindings::RemoveProperty(NPObject* np_obj,
743                                            NPIdentifier name) {
744   for (PropertyBindingList::iterator iter = property_bindings_.begin();
745        iter != property_bindings_.end();
746        ++iter) {
747     if ((*iter)->MatchesName(name)) {
748       (*iter)->RemoveProperty(this, np_obj);
749       return true;
750     }
751   }
752   return false;
753 }
754 
GetProperty(NPIdentifier name,NPVariant * result)755 bool BrowserPluginBindings::GetProperty(NPIdentifier name, NPVariant* result) {
756   for (PropertyBindingList::iterator iter = property_bindings_.begin();
757        iter != property_bindings_.end();
758        ++iter) {
759     if ((*iter)->MatchesName(name))
760       return (*iter)->GetProperty(this, result);
761   }
762   return false;
763 }
764 
765 }  // namespace content
766