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