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 WebKit::WebBindings; 32 using WebKit::WebElement; 33 using WebKit::WebDOMEvent; 34 using WebKit::WebDOMMessageEvent; 35 using WebKit::WebPluginContainer; 36 using WebKit::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 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. 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 //------------------------------------------------------------------------------ 91 NPObject* BrowserPluginBindingsAllocate(NPP npp, NPClass* the_class) { 92 return new BrowserPluginBindings::BrowserPluginNPObject; 93 } 94 95 void BrowserPluginBindingsDeallocate(NPObject* object) { 96 BrowserPluginBindings::BrowserPluginNPObject* instance = 97 static_cast<BrowserPluginBindings::BrowserPluginNPObject*>(object); 98 delete instance; 99 } 100 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 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 125 bool BrowserPluginBindingsInvokeDefault(NPObject* np_obj, 126 const NPVariant* args, 127 uint32 arg_count, 128 NPVariant* result) { 129 NOTIMPLEMENTED(); 130 return false; 131 } 132 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 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 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 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: 207 BrowserPluginMethodBinding(const char name[], uint32 arg_count) 208 : name_(name), 209 arg_count_(arg_count) { 210 } 211 212 virtual ~BrowserPluginMethodBinding() {} 213 214 bool MatchesName(NPIdentifier name) const { 215 return WebBindings::getStringIdentifier(name_.c_str()) == name; 216 } 217 218 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: 233 BrowserPluginBindingAttach() 234 : BrowserPluginMethodBinding( 235 browser_plugin::kMethodInternalAttach, 1) { 236 } 237 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(WebKit::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: 267 BrowserPluginBindingAttachWindowTo() 268 : BrowserPluginMethodBinding( 269 browser_plugin::kMethodInternalAttachWindowTo, 2) { 270 } 271 272 virtual bool Invoke(BrowserPluginBindings* bindings, 273 const NPVariant* args, 274 NPVariant* result) OVERRIDE { 275 WebKit::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 // Note: This is a method that is used internally by the <webview> shim only. 288 // This should not be exposed to developers. 289 class BrowserPluginBindingGetGuestInstanceID : 290 public BrowserPluginMethodBinding { 291 public: 292 BrowserPluginBindingGetGuestInstanceID() 293 : BrowserPluginMethodBinding( 294 browser_plugin::kMethodGetGuestInstanceId, 0) { 295 } 296 297 virtual bool Invoke(BrowserPluginBindings* bindings, 298 const NPVariant* args, 299 NPVariant* result) OVERRIDE { 300 int guest_instance_id = bindings->instance()->guest_instance_id(); 301 INT32_TO_NPVARIANT(guest_instance_id, *result); 302 return true; 303 } 304 305 private: 306 DISALLOW_COPY_AND_ASSIGN(BrowserPluginBindingGetGuestInstanceID); 307 }; 308 309 // Note: This is a method that is used internally by the <webview> shim only. 310 // This should not be exposed to developers. 311 class BrowserPluginBindingTrackObjectLifetime 312 : public BrowserPluginMethodBinding { 313 public: 314 BrowserPluginBindingTrackObjectLifetime() 315 : BrowserPluginMethodBinding( 316 browser_plugin::kMethodInternalTrackObjectLifetime, 2) { 317 } 318 319 virtual bool Invoke(BrowserPluginBindings* bindings, 320 const NPVariant* args, 321 NPVariant* result) OVERRIDE { 322 bindings->instance()->TrackObjectLifetime(args, IntFromNPVariant(args[1])); 323 return true; 324 } 325 326 private: 327 DISALLOW_COPY_AND_ASSIGN(BrowserPluginBindingTrackObjectLifetime); 328 }; 329 330 // BrowserPluginPropertyBinding ------------------------------------------------ 331 332 class BrowserPluginPropertyBinding { 333 public: 334 explicit BrowserPluginPropertyBinding(const char name[]) : name_(name) {} 335 virtual ~BrowserPluginPropertyBinding() {} 336 const std::string& name() const { return name_; } 337 bool MatchesName(NPIdentifier name) const { 338 return WebBindings::getStringIdentifier(name_.c_str()) == name; 339 } 340 virtual bool GetProperty(BrowserPluginBindings* bindings, 341 NPVariant* result) = 0; 342 virtual bool SetProperty(BrowserPluginBindings* bindings, 343 NPObject* np_obj, 344 const NPVariant* variant) = 0; 345 virtual void RemoveProperty(BrowserPluginBindings* bindings, 346 NPObject* np_obj) = 0; 347 // Updates the DOM Attribute value with the current property value. 348 void UpdateDOMAttribute(BrowserPluginBindings* bindings, 349 std::string new_value) { 350 bindings->instance()->UpdateDOMAttribute(name(), new_value); 351 } 352 private: 353 std::string name_; 354 355 DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBinding); 356 }; 357 358 class BrowserPluginPropertyBindingAutoSize 359 : public BrowserPluginPropertyBinding { 360 public: 361 BrowserPluginPropertyBindingAutoSize() 362 : BrowserPluginPropertyBinding(browser_plugin::kAttributeAutoSize) { 363 } 364 virtual bool GetProperty(BrowserPluginBindings* bindings, 365 NPVariant* result) OVERRIDE { 366 bool auto_size = bindings->instance()->GetAutoSizeAttribute(); 367 BOOLEAN_TO_NPVARIANT(auto_size, *result); 368 return true; 369 } 370 virtual bool SetProperty(BrowserPluginBindings* bindings, 371 NPObject* np_obj, 372 const NPVariant* variant) OVERRIDE { 373 std::string value = StringFromNPVariant(*variant); 374 if (!bindings->instance()->HasDOMAttribute(name())) { 375 UpdateDOMAttribute(bindings, value); 376 bindings->instance()->ParseAutoSizeAttribute(); 377 } else { 378 UpdateDOMAttribute(bindings, value); 379 } 380 return true; 381 } 382 virtual void RemoveProperty(BrowserPluginBindings* bindings, 383 NPObject* np_obj) OVERRIDE { 384 bindings->instance()->RemoveDOMAttribute(name()); 385 bindings->instance()->ParseAutoSizeAttribute(); 386 } 387 private: 388 DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingAutoSize); 389 }; 390 391 class BrowserPluginPropertyBindingContentWindow 392 : public BrowserPluginPropertyBinding { 393 public: 394 BrowserPluginPropertyBindingContentWindow() 395 : BrowserPluginPropertyBinding(browser_plugin::kAttributeContentWindow) { 396 } 397 virtual bool GetProperty(BrowserPluginBindings* bindings, 398 NPVariant* result) OVERRIDE { 399 NPObject* obj = bindings->instance()->GetContentWindow(); 400 if (obj) { 401 result->type = NPVariantType_Object; 402 result->value.objectValue = WebBindings::retainObject(obj); 403 } 404 return true; 405 } 406 virtual bool SetProperty(BrowserPluginBindings* bindings, 407 NPObject* np_obj, 408 const NPVariant* variant) OVERRIDE { 409 return false; 410 } 411 virtual void RemoveProperty(BrowserPluginBindings* bindings, 412 NPObject* np_obj) OVERRIDE {} 413 private: 414 DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingContentWindow); 415 }; 416 417 class BrowserPluginPropertyBindingMaxHeight 418 : public BrowserPluginPropertyBinding { 419 public: 420 BrowserPluginPropertyBindingMaxHeight() 421 : BrowserPluginPropertyBinding(browser_plugin::kAttributeMaxHeight) { 422 } 423 virtual bool GetProperty(BrowserPluginBindings* bindings, 424 NPVariant* result) OVERRIDE { 425 int max_height = bindings->instance()->GetMaxHeightAttribute(); 426 INT32_TO_NPVARIANT(max_height, *result); 427 return true; 428 } 429 virtual bool SetProperty(BrowserPluginBindings* bindings, 430 NPObject* np_obj, 431 const NPVariant* variant) OVERRIDE { 432 int new_value = IntFromNPVariant(*variant); 433 if (bindings->instance()->GetMaxHeightAttribute() != new_value) { 434 UpdateDOMAttribute(bindings, base::IntToString(new_value)); 435 bindings->instance()->ParseSizeContraintsChanged(); 436 } 437 return true; 438 } 439 virtual void RemoveProperty(BrowserPluginBindings* bindings, 440 NPObject* np_obj) OVERRIDE { 441 bindings->instance()->RemoveDOMAttribute(name()); 442 bindings->instance()->ParseSizeContraintsChanged(); 443 } 444 private: 445 DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingMaxHeight); 446 }; 447 448 class BrowserPluginPropertyBindingMaxWidth 449 : public BrowserPluginPropertyBinding { 450 public: 451 BrowserPluginPropertyBindingMaxWidth() 452 : BrowserPluginPropertyBinding(browser_plugin::kAttributeMaxWidth) { 453 } 454 virtual bool GetProperty(BrowserPluginBindings* bindings, 455 NPVariant* result) OVERRIDE { 456 int max_width = bindings->instance()->GetMaxWidthAttribute(); 457 INT32_TO_NPVARIANT(max_width, *result); 458 return true; 459 } 460 virtual bool SetProperty(BrowserPluginBindings* bindings, 461 NPObject* np_obj, 462 const NPVariant* variant) OVERRIDE { 463 int new_value = IntFromNPVariant(*variant); 464 if (bindings->instance()->GetMaxWidthAttribute() != new_value) { 465 UpdateDOMAttribute(bindings, base::IntToString(new_value)); 466 bindings->instance()->ParseSizeContraintsChanged(); 467 } 468 return true; 469 } 470 virtual void RemoveProperty(BrowserPluginBindings* bindings, 471 NPObject* np_obj) OVERRIDE { 472 bindings->instance()->RemoveDOMAttribute(name()); 473 bindings->instance()->ParseSizeContraintsChanged(); 474 } 475 private: 476 DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingMaxWidth); 477 }; 478 479 class BrowserPluginPropertyBindingMinHeight 480 : public BrowserPluginPropertyBinding { 481 public: 482 BrowserPluginPropertyBindingMinHeight() 483 : BrowserPluginPropertyBinding(browser_plugin::kAttributeMinHeight) { 484 } 485 virtual bool GetProperty(BrowserPluginBindings* bindings, 486 NPVariant* result) OVERRIDE { 487 int min_height = bindings->instance()->GetMinHeightAttribute(); 488 INT32_TO_NPVARIANT(min_height, *result); 489 return true; 490 } 491 virtual bool SetProperty(BrowserPluginBindings* bindings, 492 NPObject* np_obj, 493 const NPVariant* variant) OVERRIDE { 494 int new_value = IntFromNPVariant(*variant); 495 if (bindings->instance()->GetMinHeightAttribute() != new_value) { 496 UpdateDOMAttribute(bindings, base::IntToString(new_value)); 497 bindings->instance()->ParseSizeContraintsChanged(); 498 } 499 return true; 500 } 501 virtual void RemoveProperty(BrowserPluginBindings* bindings, 502 NPObject* np_obj) OVERRIDE { 503 bindings->instance()->RemoveDOMAttribute(name()); 504 bindings->instance()->ParseSizeContraintsChanged(); 505 } 506 private: 507 DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingMinHeight); 508 }; 509 510 class BrowserPluginPropertyBindingMinWidth 511 : public BrowserPluginPropertyBinding { 512 public: 513 BrowserPluginPropertyBindingMinWidth() 514 : BrowserPluginPropertyBinding(browser_plugin::kAttributeMinWidth) { 515 } 516 virtual bool GetProperty(BrowserPluginBindings* bindings, 517 NPVariant* result) OVERRIDE { 518 int min_width = bindings->instance()->GetMinWidthAttribute(); 519 INT32_TO_NPVARIANT(min_width, *result); 520 return true; 521 } 522 virtual bool SetProperty(BrowserPluginBindings* bindings, 523 NPObject* np_obj, 524 const NPVariant* variant) OVERRIDE { 525 int new_value = IntFromNPVariant(*variant); 526 if (bindings->instance()->GetMinWidthAttribute() != new_value) { 527 UpdateDOMAttribute(bindings, base::IntToString(new_value)); 528 bindings->instance()->ParseSizeContraintsChanged(); 529 } 530 return true; 531 } 532 virtual void RemoveProperty(BrowserPluginBindings* bindings, 533 NPObject* np_obj) OVERRIDE { 534 bindings->instance()->RemoveDOMAttribute(name()); 535 bindings->instance()->ParseSizeContraintsChanged(); 536 } 537 private: 538 DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingMinWidth); 539 }; 540 541 class BrowserPluginPropertyBindingName 542 : public BrowserPluginPropertyBinding { 543 public: 544 BrowserPluginPropertyBindingName() 545 : BrowserPluginPropertyBinding(browser_plugin::kAttributeName) { 546 } 547 virtual bool GetProperty(BrowserPluginBindings* bindings, 548 NPVariant* result) OVERRIDE { 549 std::string name = bindings->instance()->GetNameAttribute(); 550 return StringToNPVariant(name, result); 551 return true; 552 } 553 virtual bool SetProperty(BrowserPluginBindings* bindings, 554 NPObject* np_obj, 555 const NPVariant* variant) OVERRIDE { 556 std::string new_value = StringFromNPVariant(*variant); 557 if (bindings->instance()->GetNameAttribute() != new_value) { 558 UpdateDOMAttribute(bindings, new_value); 559 bindings->instance()->ParseNameAttribute(); 560 } 561 return true; 562 } 563 virtual void RemoveProperty(BrowserPluginBindings* bindings, 564 NPObject* np_obj) OVERRIDE { 565 bindings->instance()->RemoveDOMAttribute(name()); 566 bindings->instance()->ParseNameAttribute(); 567 } 568 private: 569 DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingName); 570 }; 571 572 class BrowserPluginPropertyBindingPartition 573 : public BrowserPluginPropertyBinding { 574 public: 575 BrowserPluginPropertyBindingPartition() 576 : BrowserPluginPropertyBinding(browser_plugin::kAttributePartition) { 577 } 578 virtual bool GetProperty(BrowserPluginBindings* bindings, 579 NPVariant* result) OVERRIDE { 580 std::string partition_id = bindings->instance()->GetPartitionAttribute(); 581 return StringToNPVariant(partition_id, result); 582 } 583 virtual bool SetProperty(BrowserPluginBindings* bindings, 584 NPObject* np_obj, 585 const NPVariant* variant) OVERRIDE { 586 std::string new_value = StringFromNPVariant(*variant); 587 std::string old_value = bindings->instance()->GetPartitionAttribute(); 588 if (old_value != new_value) { 589 UpdateDOMAttribute(bindings, new_value); 590 std::string error_message; 591 if (!bindings->instance()->ParsePartitionAttribute(&error_message)) { 592 WebBindings::setException( 593 np_obj, static_cast<const NPUTF8 *>(error_message.c_str())); 594 // Reset to old value on error. 595 UpdateDOMAttribute(bindings, old_value); 596 return false; 597 } 598 } 599 return true; 600 } 601 virtual void RemoveProperty(BrowserPluginBindings* bindings, 602 NPObject* np_obj) OVERRIDE { 603 std::string error_message; 604 if (bindings->instance()->CanRemovePartitionAttribute(&error_message)) { 605 bindings->instance()->RemoveDOMAttribute(name()); 606 } else { 607 WebBindings::setException( 608 np_obj, static_cast<const NPUTF8 *>(error_message.c_str())); 609 } 610 } 611 private: 612 DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingPartition); 613 }; 614 615 class BrowserPluginPropertyBindingSrc : public BrowserPluginPropertyBinding { 616 public: 617 BrowserPluginPropertyBindingSrc() 618 : BrowserPluginPropertyBinding(browser_plugin::kAttributeSrc) { 619 } 620 virtual bool GetProperty(BrowserPluginBindings* bindings, 621 NPVariant* result) OVERRIDE { 622 std::string src = bindings->instance()->GetSrcAttribute(); 623 return StringToNPVariant(src, result); 624 } 625 virtual bool SetProperty(BrowserPluginBindings* bindings, 626 NPObject* np_obj, 627 const NPVariant* variant) OVERRIDE { 628 std::string new_value = StringFromNPVariant(*variant); 629 // We should not be issuing navigation IPCs if we attempt to set the 630 // src property to the empty string. Instead, we want to simply restore 631 // the src attribute back to its old value. 632 if (new_value.empty()) { 633 RemoveProperty(bindings, np_obj); 634 return true; 635 } 636 std::string old_value = bindings->instance()->GetSrcAttribute(); 637 bool guest_crashed = bindings->instance()->guest_crashed(); 638 if ((old_value != new_value) || guest_crashed) { 639 // If the new value was empty then we're effectively resetting the 640 // attribute to the old value here. This will be picked up by <webview>'s 641 // mutation observer and will restore the src attribute after it has been 642 // removed. 643 UpdateDOMAttribute(bindings, new_value); 644 std::string error_message; 645 if (!bindings->instance()->ParseSrcAttribute(&error_message)) { 646 WebBindings::setException( 647 np_obj, static_cast<const NPUTF8 *>(error_message.c_str())); 648 // Reset to old value on error. 649 UpdateDOMAttribute(bindings, old_value); 650 return false; 651 } 652 } 653 return true; 654 } 655 virtual void RemoveProperty(BrowserPluginBindings* bindings, 656 NPObject* np_obj) OVERRIDE { 657 std::string old_value = bindings->instance()->GetSrcAttribute(); 658 // Remove the DOM attribute to trigger the mutation observer when it is 659 // restored to its original value again. 660 bindings->instance()->RemoveDOMAttribute(name()); 661 UpdateDOMAttribute(bindings, old_value); 662 } 663 private: 664 DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingSrc); 665 }; 666 667 668 // BrowserPluginBindings ------------------------------------------------------ 669 670 BrowserPluginBindings::BrowserPluginNPObject::BrowserPluginNPObject() { 671 } 672 673 BrowserPluginBindings::BrowserPluginNPObject::~BrowserPluginNPObject() { 674 } 675 676 BrowserPluginBindings::BrowserPluginBindings(BrowserPlugin* instance) 677 : instance_(instance), 678 np_object_(NULL), 679 weak_ptr_factory_(this) { 680 NPObject* obj = 681 WebBindings::createObject(instance->pluginNPP(), 682 &browser_plugin_message_class); 683 np_object_ = static_cast<BrowserPluginBindings::BrowserPluginNPObject*>(obj); 684 np_object_->message_channel = weak_ptr_factory_.GetWeakPtr(); 685 686 method_bindings_.push_back(new BrowserPluginBindingAttach); 687 method_bindings_.push_back(new BrowserPluginBindingAttachWindowTo); 688 method_bindings_.push_back(new BrowserPluginBindingGetGuestInstanceID); 689 method_bindings_.push_back(new BrowserPluginBindingTrackObjectLifetime); 690 691 property_bindings_.push_back(new BrowserPluginPropertyBindingAutoSize); 692 property_bindings_.push_back(new BrowserPluginPropertyBindingContentWindow); 693 property_bindings_.push_back(new BrowserPluginPropertyBindingMaxHeight); 694 property_bindings_.push_back(new BrowserPluginPropertyBindingMaxWidth); 695 property_bindings_.push_back(new BrowserPluginPropertyBindingMinHeight); 696 property_bindings_.push_back(new BrowserPluginPropertyBindingMinWidth); 697 property_bindings_.push_back(new BrowserPluginPropertyBindingName); 698 property_bindings_.push_back(new BrowserPluginPropertyBindingPartition); 699 property_bindings_.push_back(new BrowserPluginPropertyBindingSrc); 700 } 701 702 BrowserPluginBindings::~BrowserPluginBindings() { 703 WebBindings::releaseObject(np_object_); 704 } 705 706 bool BrowserPluginBindings::HasMethod(NPIdentifier name) const { 707 for (BindingList::const_iterator iter = method_bindings_.begin(); 708 iter != method_bindings_.end(); 709 ++iter) { 710 if ((*iter)->MatchesName(name)) 711 return true; 712 } 713 return false; 714 } 715 716 bool BrowserPluginBindings::InvokeMethod(NPIdentifier name, 717 const NPVariant* args, 718 uint32 arg_count, 719 NPVariant* result) { 720 for (BindingList::iterator iter = method_bindings_.begin(); 721 iter != method_bindings_.end(); 722 ++iter) { 723 if ((*iter)->MatchesName(name) && (*iter)->arg_count() == arg_count) 724 return (*iter)->Invoke(this, args, result); 725 } 726 return false; 727 } 728 729 bool BrowserPluginBindings::HasProperty(NPIdentifier name) const { 730 for (PropertyBindingList::const_iterator iter = property_bindings_.begin(); 731 iter != property_bindings_.end(); 732 ++iter) { 733 if ((*iter)->MatchesName(name)) 734 return true; 735 } 736 return false; 737 } 738 739 bool BrowserPluginBindings::SetProperty(NPObject* np_obj, 740 NPIdentifier name, 741 const NPVariant* variant) { 742 for (PropertyBindingList::iterator iter = property_bindings_.begin(); 743 iter != property_bindings_.end(); 744 ++iter) { 745 if ((*iter)->MatchesName(name)) { 746 if ((*iter)->SetProperty(this, np_obj, variant)) { 747 return true; 748 } 749 break; 750 } 751 } 752 return false; 753 } 754 755 bool BrowserPluginBindings::RemoveProperty(NPObject* np_obj, 756 NPIdentifier name) { 757 for (PropertyBindingList::iterator iter = property_bindings_.begin(); 758 iter != property_bindings_.end(); 759 ++iter) { 760 if ((*iter)->MatchesName(name)) { 761 (*iter)->RemoveProperty(this, np_obj); 762 return true; 763 } 764 } 765 return false; 766 } 767 768 bool BrowserPluginBindings::GetProperty(NPIdentifier name, NPVariant* result) { 769 for (PropertyBindingList::iterator iter = property_bindings_.begin(); 770 iter != property_bindings_.end(); 771 ++iter) { 772 if ((*iter)->MatchesName(name)) 773 return (*iter)->GetProperty(this, result); 774 } 775 return false; 776 } 777 778 } // namespace content 779