Home | History | Annotate | Download | only in browser_plugin
      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 
     42 BrowserPluginBindings* GetBindings(NPObject* object) {
     43   return static_cast<BrowserPluginBindings::BrowserPluginNPObject*>(object)->
     44       message_channel.get();
     45 }
     46 
     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 
     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) {
     58   int value = 0;
     59   switch (variant.type) {
     60     case NPVariantType_Double:
     61       value = NPVARIANT_TO_DOUBLE(variant);
     62       break;
     63     case NPVariantType_Int32:
     64       value = NPVARIANT_TO_INT32(variant);
     65       break;
     66     case NPVariantType_String:
     67       base::StringToInt(StringFromNPVariant(variant), &value);
     68       break;
     69     default:
     70       break;
     71   }
     72   return value;
     73 }
     74 
     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;
     81 }
     82 
     83 void BrowserPluginBindingsDeallocate(NPObject* object) {
     84   BrowserPluginBindings::BrowserPluginNPObject* instance =
     85       static_cast<BrowserPluginBindings::BrowserPluginNPObject*>(object);
     86   delete instance;
     87 }
     88 
     89 bool BrowserPluginBindingsHasMethod(NPObject* np_obj, NPIdentifier name) {
     90   if (!np_obj)
     91     return false;
     92 
     93   BrowserPluginBindings* bindings = GetBindings(np_obj);
     94   if (!bindings)
     95     return false;
     96 
     97   return bindings->HasMethod(name);
     98 }
     99 
    100 bool BrowserPluginBindingsInvoke(NPObject* np_obj, NPIdentifier name,
    101                                  const NPVariant* args, uint32 arg_count,
    102                                  NPVariant* result) {
    103   if (!np_obj)
    104     return false;
    105 
    106   BrowserPluginBindings* bindings = GetBindings(np_obj);
    107   if (!bindings)
    108     return false;
    109 
    110   return bindings->InvokeMethod(name, args, arg_count, result);
    111 }
    112 
    113 bool BrowserPluginBindingsInvokeDefault(NPObject* np_obj,
    114                                         const NPVariant* args,
    115                                         uint32 arg_count,
    116                                         NPVariant* result) {
    117   NOTIMPLEMENTED();
    118   return false;
    119 }
    120 
    121 bool BrowserPluginBindingsHasProperty(NPObject* np_obj, NPIdentifier name) {
    122   if (!np_obj)
    123     return false;
    124 
    125   BrowserPluginBindings* bindings = GetBindings(np_obj);
    126   if (!bindings)
    127     return false;
    128 
    129   return bindings->HasProperty(name);
    130 }
    131 
    132 bool BrowserPluginBindingsGetProperty(NPObject* np_obj, NPIdentifier name,
    133                                       NPVariant* result) {
    134   if (!np_obj)
    135     return false;
    136 
    137   if (!result)
    138     return false;
    139 
    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);
    143   if (!bindings)
    144     return false;
    145 
    146   return bindings->GetProperty(name, result);
    147 }
    148 
    149 bool BrowserPluginBindingsSetProperty(NPObject* np_obj, NPIdentifier name,
    150                                       const NPVariant* variant) {
    151   if (!np_obj)
    152     return false;
    153   if (!variant)
    154     return false;
    155 
    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);
    159   if (!bindings)
    160     return false;
    161 
    162   if (variant->type == NPVariantType_Null)
    163     return bindings->RemoveProperty(np_obj, name);
    164 
    165   return bindings->SetProperty(np_obj, name, variant);
    166 }
    167 
    168 bool BrowserPluginBindingsEnumerate(NPObject *np_obj, NPIdentifier **value,
    169                                     uint32_t *count) {
    170   NOTIMPLEMENTED();
    171   return true;
    172 }
    173 
    174 NPClass browser_plugin_message_class = {
    175   NP_CLASS_STRUCT_VERSION,
    176   &BrowserPluginBindingsAllocate,
    177   &BrowserPluginBindingsDeallocate,
    178   NULL,
    179   &BrowserPluginBindingsHasMethod,
    180   &BrowserPluginBindingsInvoke,
    181   &BrowserPluginBindingsInvokeDefault,
    182   &BrowserPluginBindingsHasProperty,
    183   &BrowserPluginBindingsGetProperty,
    184   &BrowserPluginBindingsSetProperty,
    185   NULL,
    186   &BrowserPluginBindingsEnumerate,
    187 };
    188 
    189 }  // namespace
    190 
    191 // BrowserPluginMethodBinding --------------------------------------------------
    192 
    193 class BrowserPluginMethodBinding {
    194  public:
    195   BrowserPluginMethodBinding(const char name[], uint32 arg_count)
    196       : name_(name),
    197         arg_count_(arg_count) {
    198   }
    199 
    200   virtual ~BrowserPluginMethodBinding() {}
    201 
    202   bool MatchesName(NPIdentifier name) const {
    203     return WebBindings::getStringIdentifier(name_.c_str()) == name;
    204   }
    205 
    206   uint32 arg_count() const { return arg_count_; }
    207 
    208   virtual bool Invoke(BrowserPluginBindings* bindings,
    209                       const NPVariant* args,
    210                       NPVariant* result) = 0;
    211 
    212  private:
    213   std::string name_;
    214   uint32 arg_count_;
    215 
    216   DISALLOW_COPY_AND_ASSIGN(BrowserPluginMethodBinding);
    217 };
    218 
    219 class BrowserPluginBindingAttach: public BrowserPluginMethodBinding {
    220  public:
    221   BrowserPluginBindingAttach()
    222       : BrowserPluginMethodBinding(browser_plugin::kMethodInternalAttach, 2) {}
    223 
    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);
    229     return true;
    230   }
    231 
    232  private:
    233   bool InvokeHelper(BrowserPluginBindings* bindings, const NPVariant* args) {
    234     if (!bindings->instance()->render_view())
    235       return false;
    236 
    237     int instance_id = IntFromNPVariant(args[0]);
    238     if (!instance_id)
    239       return false;
    240 
    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()));
    246     if (!value)
    247       return false;
    248 
    249     if (!value->IsType(base::Value::TYPE_DICTIONARY))
    250       return false;
    251 
    252     scoped_ptr<base::DictionaryValue> extra_params(
    253         static_cast<base::DictionaryValue*>(value.release()));
    254     bindings->instance()->Attach(instance_id, extra_params.Pass());
    255     return true;
    256   }
    257   DISALLOW_COPY_AND_ASSIGN(BrowserPluginBindingAttach);
    258 };
    259 
    260 // BrowserPluginPropertyBinding ------------------------------------------------
    261 
    262 class BrowserPluginPropertyBinding {
    263  public:
    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;
    269   }
    270   virtual bool GetProperty(BrowserPluginBindings* bindings,
    271                            NPVariant* result) = 0;
    272   virtual bool SetProperty(BrowserPluginBindings* bindings,
    273                            NPObject* np_obj,
    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);
    281   }
    282  private:
    283   std::string name_;
    284 
    285   DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBinding);
    286 };
    287 
    288 class BrowserPluginPropertyBindingAllowTransparency
    289     : public BrowserPluginPropertyBinding {
    290  public:
    291   BrowserPluginPropertyBindingAllowTransparency()
    292       : BrowserPluginPropertyBinding(
    293           browser_plugin::kAttributeAllowTransparency) {
    294   }
    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);
    300     return true;
    301   }
    302   virtual bool SetProperty(BrowserPluginBindings* bindings,
    303                            NPObject* np_obj,
    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();
    309     } else {
    310       UpdateDOMAttribute(bindings, value);
    311     }
    312     return true;
    313   }
    314   virtual void RemoveProperty(BrowserPluginBindings* bindings,
    315                               NPObject* np_obj) OVERRIDE {
    316     bindings->instance()->RemoveDOMAttribute(name());
    317     bindings->instance()->ParseAllowTransparencyAttribute();
    318   }
    319  private:
    320   DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingAllowTransparency);
    321 };
    322 
    323 class BrowserPluginPropertyBindingAutoSize
    324     : public BrowserPluginPropertyBinding {
    325  public:
    326   BrowserPluginPropertyBindingAutoSize()
    327       : BrowserPluginPropertyBinding(browser_plugin::kAttributeAutoSize) {
    328   }
    329   virtual bool GetProperty(BrowserPluginBindings* bindings,
    330                            NPVariant* result) OVERRIDE {
    331     bool auto_size = bindings->instance()->GetAutoSizeAttribute();
    332     BOOLEAN_TO_NPVARIANT(auto_size, *result);
    333     return true;
    334   }
    335   virtual bool SetProperty(BrowserPluginBindings* bindings,
    336                            NPObject* np_obj,
    337                            const NPVariant* variant) OVERRIDE {
    338     std::string value = StringFromNPVariant(*variant);
    339     if (!bindings->instance()->HasDOMAttribute(name())) {
    340       UpdateDOMAttribute(bindings, value);
    341       bindings->instance()->ParseAutoSizeAttribute();
    342     } else {
    343       UpdateDOMAttribute(bindings, value);
    344     }
    345     return true;
    346   }
    347   virtual void RemoveProperty(BrowserPluginBindings* bindings,
    348                               NPObject* np_obj) OVERRIDE {
    349     bindings->instance()->RemoveDOMAttribute(name());
    350     bindings->instance()->ParseAutoSizeAttribute();
    351   }
    352  private:
    353   DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingAutoSize);
    354 };
    355 
    356 class BrowserPluginPropertyBindingContentWindow
    357     : public BrowserPluginPropertyBinding {
    358  public:
    359   BrowserPluginPropertyBindingContentWindow()
    360       : BrowserPluginPropertyBinding(browser_plugin::kAttributeContentWindow) {
    361   }
    362   virtual bool GetProperty(BrowserPluginBindings* bindings,
    363                            NPVariant* result) OVERRIDE {
    364     NPObject* obj = bindings->instance()->GetContentWindow();
    365     if (obj) {
    366       result->type = NPVariantType_Object;
    367       result->value.objectValue = WebBindings::retainObject(obj);
    368     }
    369     return true;
    370   }
    371   virtual bool SetProperty(BrowserPluginBindings* bindings,
    372                            NPObject* np_obj,
    373                            const NPVariant* variant) OVERRIDE {
    374     return false;
    375   }
    376   virtual void RemoveProperty(BrowserPluginBindings* bindings,
    377                               NPObject* np_obj) OVERRIDE {}
    378  private:
    379   DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingContentWindow);
    380 };
    381 
    382 class BrowserPluginPropertyBindingMaxHeight
    383     : public BrowserPluginPropertyBinding {
    384  public:
    385   BrowserPluginPropertyBindingMaxHeight()
    386       : BrowserPluginPropertyBinding(browser_plugin::kAttributeMaxHeight) {
    387   }
    388   virtual bool GetProperty(BrowserPluginBindings* bindings,
    389                            NPVariant* result) OVERRIDE {
    390     int max_height = bindings->instance()->GetMaxHeightAttribute();
    391     INT32_TO_NPVARIANT(max_height, *result);
    392     return true;
    393   }
    394   virtual bool SetProperty(BrowserPluginBindings* bindings,
    395                            NPObject* np_obj,
    396                            const NPVariant* variant) OVERRIDE {
    397     int new_value = IntFromNPVariant(*variant);
    398     if (bindings->instance()->GetMaxHeightAttribute() != new_value) {
    399       UpdateDOMAttribute(bindings, base::IntToString(new_value));
    400       bindings->instance()->ParseSizeContraintsChanged();
    401     }
    402     return true;
    403   }
    404   virtual void RemoveProperty(BrowserPluginBindings* bindings,
    405                               NPObject* np_obj) OVERRIDE {
    406     bindings->instance()->RemoveDOMAttribute(name());
    407     bindings->instance()->ParseSizeContraintsChanged();
    408   }
    409  private:
    410   DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingMaxHeight);
    411 };
    412 
    413 class BrowserPluginPropertyBindingMaxWidth
    414     : public BrowserPluginPropertyBinding {
    415  public:
    416   BrowserPluginPropertyBindingMaxWidth()
    417       : BrowserPluginPropertyBinding(browser_plugin::kAttributeMaxWidth) {
    418   }
    419   virtual bool GetProperty(BrowserPluginBindings* bindings,
    420                            NPVariant* result) OVERRIDE {
    421     int max_width = bindings->instance()->GetMaxWidthAttribute();
    422     INT32_TO_NPVARIANT(max_width, *result);
    423     return true;
    424   }
    425   virtual bool SetProperty(BrowserPluginBindings* bindings,
    426                            NPObject* np_obj,
    427                            const NPVariant* variant) OVERRIDE {
    428     int new_value = IntFromNPVariant(*variant);
    429     if (bindings->instance()->GetMaxWidthAttribute() != new_value) {
    430       UpdateDOMAttribute(bindings, base::IntToString(new_value));
    431       bindings->instance()->ParseSizeContraintsChanged();
    432     }
    433     return true;
    434   }
    435   virtual void RemoveProperty(BrowserPluginBindings* bindings,
    436                               NPObject* np_obj) OVERRIDE {
    437     bindings->instance()->RemoveDOMAttribute(name());
    438     bindings->instance()->ParseSizeContraintsChanged();
    439   }
    440  private:
    441   DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingMaxWidth);
    442 };
    443 
    444 class BrowserPluginPropertyBindingMinHeight
    445     : public BrowserPluginPropertyBinding {
    446  public:
    447   BrowserPluginPropertyBindingMinHeight()
    448       : BrowserPluginPropertyBinding(browser_plugin::kAttributeMinHeight) {
    449   }
    450   virtual bool GetProperty(BrowserPluginBindings* bindings,
    451                            NPVariant* result) OVERRIDE {
    452     int min_height = bindings->instance()->GetMinHeightAttribute();
    453     INT32_TO_NPVARIANT(min_height, *result);
    454     return true;
    455   }
    456   virtual bool SetProperty(BrowserPluginBindings* bindings,
    457                            NPObject* np_obj,
    458                            const NPVariant* variant) OVERRIDE {
    459     int new_value = IntFromNPVariant(*variant);
    460     if (bindings->instance()->GetMinHeightAttribute() != new_value) {
    461       UpdateDOMAttribute(bindings, base::IntToString(new_value));
    462       bindings->instance()->ParseSizeContraintsChanged();
    463     }
    464     return true;
    465   }
    466   virtual void RemoveProperty(BrowserPluginBindings* bindings,
    467                               NPObject* np_obj) OVERRIDE {
    468     bindings->instance()->RemoveDOMAttribute(name());
    469     bindings->instance()->ParseSizeContraintsChanged();
    470   }
    471  private:
    472   DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingMinHeight);
    473 };
    474 
    475 class BrowserPluginPropertyBindingMinWidth
    476     : public BrowserPluginPropertyBinding {
    477  public:
    478   BrowserPluginPropertyBindingMinWidth()
    479       : BrowserPluginPropertyBinding(browser_plugin::kAttributeMinWidth) {
    480   }
    481   virtual bool GetProperty(BrowserPluginBindings* bindings,
    482                            NPVariant* result) OVERRIDE {
    483     int min_width = bindings->instance()->GetMinWidthAttribute();
    484     INT32_TO_NPVARIANT(min_width, *result);
    485     return true;
    486   }
    487   virtual bool SetProperty(BrowserPluginBindings* bindings,
    488                            NPObject* np_obj,
    489                            const NPVariant* variant) OVERRIDE {
    490     int new_value = IntFromNPVariant(*variant);
    491     if (bindings->instance()->GetMinWidthAttribute() != new_value) {
    492       UpdateDOMAttribute(bindings, base::IntToString(new_value));
    493       bindings->instance()->ParseSizeContraintsChanged();
    494     }
    495     return true;
    496   }
    497   virtual void RemoveProperty(BrowserPluginBindings* bindings,
    498                               NPObject* np_obj) OVERRIDE {
    499     bindings->instance()->RemoveDOMAttribute(name());
    500     bindings->instance()->ParseSizeContraintsChanged();
    501   }
    502  private:
    503   DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingMinWidth);
    504 };
    505 
    506 
    507 // BrowserPluginBindings ------------------------------------------------------
    508 
    509 BrowserPluginBindings::BrowserPluginNPObject::BrowserPluginNPObject() {
    510 }
    511 
    512 BrowserPluginBindings::BrowserPluginNPObject::~BrowserPluginNPObject() {
    513 }
    514 
    515 BrowserPluginBindings::BrowserPluginBindings(BrowserPlugin* instance)
    516     : instance_(instance),
    517       np_object_(NULL),
    518       weak_ptr_factory_(this) {
    519   NPObject* obj =
    520       WebBindings::createObject(instance->pluginNPP(),
    521                                 &browser_plugin_message_class);
    522   np_object_ = static_cast<BrowserPluginBindings::BrowserPluginNPObject*>(obj);
    523   np_object_->message_channel = weak_ptr_factory_.GetWeakPtr();
    524 
    525   method_bindings_.push_back(new BrowserPluginBindingAttach);
    526 
    527   property_bindings_.push_back(
    528       new BrowserPluginPropertyBindingAllowTransparency);
    529   property_bindings_.push_back(new BrowserPluginPropertyBindingAutoSize);
    530   property_bindings_.push_back(new BrowserPluginPropertyBindingContentWindow);
    531   property_bindings_.push_back(new BrowserPluginPropertyBindingMaxHeight);
    532   property_bindings_.push_back(new BrowserPluginPropertyBindingMaxWidth);
    533   property_bindings_.push_back(new BrowserPluginPropertyBindingMinHeight);
    534   property_bindings_.push_back(new BrowserPluginPropertyBindingMinWidth);
    535 }
    536 
    537 BrowserPluginBindings::~BrowserPluginBindings() {
    538   WebBindings::releaseObject(np_object_);
    539 }
    540 
    541 bool BrowserPluginBindings::HasMethod(NPIdentifier name) const {
    542   for (BindingList::const_iterator iter = method_bindings_.begin();
    543        iter != method_bindings_.end();
    544        ++iter) {
    545     if ((*iter)->MatchesName(name))
    546       return true;
    547   }
    548   return false;
    549 }
    550 
    551 bool BrowserPluginBindings::InvokeMethod(NPIdentifier name,
    552                                          const NPVariant* args,
    553                                          uint32 arg_count,
    554                                          NPVariant* result) {
    555   for (BindingList::iterator iter = method_bindings_.begin();
    556        iter != method_bindings_.end();
    557        ++iter) {
    558     if ((*iter)->MatchesName(name) && (*iter)->arg_count() == arg_count)
    559       return (*iter)->Invoke(this, args, result);
    560   }
    561   return false;
    562 }
    563 
    564 bool BrowserPluginBindings::HasProperty(NPIdentifier name) const {
    565   for (PropertyBindingList::const_iterator iter = property_bindings_.begin();
    566        iter != property_bindings_.end();
    567        ++iter) {
    568     if ((*iter)->MatchesName(name))
    569       return true;
    570   }
    571   return false;
    572 }
    573 
    574 bool BrowserPluginBindings::SetProperty(NPObject* np_obj,
    575                                         NPIdentifier name,
    576                                         const NPVariant* variant) {
    577   for (PropertyBindingList::iterator iter = property_bindings_.begin();
    578        iter != property_bindings_.end();
    579        ++iter) {
    580     if ((*iter)->MatchesName(name)) {
    581       if ((*iter)->SetProperty(this, np_obj, variant)) {
    582         return true;
    583       }
    584       break;
    585     }
    586   }
    587   return false;
    588 }
    589 
    590 bool BrowserPluginBindings::RemoveProperty(NPObject* np_obj,
    591                                            NPIdentifier name) {
    592   for (PropertyBindingList::iterator iter = property_bindings_.begin();
    593        iter != property_bindings_.end();
    594        ++iter) {
    595     if ((*iter)->MatchesName(name)) {
    596       (*iter)->RemoveProperty(this, np_obj);
    597       return true;
    598     }
    599   }
    600   return false;
    601 }
    602 
    603 bool BrowserPluginBindings::GetProperty(NPIdentifier name, NPVariant* result) {
    604   for (PropertyBindingList::iterator iter = property_bindings_.begin();
    605        iter != property_bindings_.end();
    606        ++iter) {
    607     if ((*iter)->MatchesName(name))
    608       return (*iter)->GetProperty(this, result);
    609   }
    610   return false;
    611 }
    612 
    613 }  // namespace content
    614