Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(315)

Side by Side Diff: content/renderer/browser_plugin/browser_plugin_bindings.cc

Issue 10830072: Browser Plugin: New Implementation (Renderer Side) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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/logging.h"
12 #include "base/message_loop.h"
13 #include "base/string16.h"
14 #include "base/string_split.h"
15 #include "base/utf_string_conversions.h"
16 #include "content/renderer/browser_plugin/browser_plugin.h"
17 #include "third_party/npapi/bindings/npapi.h"
18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebBindings.h"
19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDOMMessageEvent.h"
21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h"
22 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
23 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h"
24 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginContainer.h"
25 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSerialize dScriptValue.h"
26 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h"
27 #include "v8/include/v8.h"
28
29 using WebKit::WebBindings;
30 using WebKit::WebElement;
31 using WebKit::WebDOMEvent;
32 using WebKit::WebDOMMessageEvent;
33 using WebKit::WebPluginContainer;
34 using WebKit::WebSerializedScriptValue;
35 using WebKit::WebString;
36
37 namespace content {
38
39 namespace browser_plugin {
40
41 namespace {
42
43 const char kAddEventListener[] = "addEventListener";
44 const char kRemoveEventListener[] = "removeEventListener";
45 const char kPostMessage[] = "postMessage";
46 const char kSrcAttribute[] = "src";
47
48 BrowserPluginBindings* GetBindings(NPObject* object) {
49 return static_cast<BrowserPluginBindings::BrowserPluginNPObject*>(object)->
50 message_channel;
51 }
52
53 bool IdentifierIsAddEventListener(NPIdentifier identifier) {
54 return WebBindings::getStringIdentifier(kAddEventListener) == identifier;
55 }
56
57 bool IdentifierIsRemoveEventListener(NPIdentifier identifier) {
58 return WebBindings::getStringIdentifier(kRemoveEventListener) == identifier;
59 }
60
61 bool IdentifierIsPostMessage(NPIdentifier identifier) {
62 return WebBindings::getStringIdentifier(kPostMessage) == identifier;
63 }
64
65 bool IdentifierIsSrcAttribute(NPIdentifier identifier) {
66 return WebBindings::getStringIdentifier(kSrcAttribute) == identifier;
67 }
68
69 std::string StringFromNPVariant(const NPVariant& variant) {
70 if (!NPVARIANT_IS_STRING(variant))
71 return std::string();
72 const NPString& np_string = NPVARIANT_TO_STRING(variant);
73 return std::string(np_string.UTF8Characters, np_string.UTF8Length);
74 }
75
76 string16 String16FromNPVariant(const NPVariant& variant) {
77 if (!NPVARIANT_IS_STRING(variant))
78 return string16();
79 const NPString& np_string = NPVARIANT_TO_STRING(variant);
80 string16 wstr;
81 if (!UTF8ToUTF16(np_string.UTF8Characters, np_string.UTF8Length, &wstr))
82 return string16();
83 return wstr;
84 }
85
86 bool StringToNPVariant(const std::string &in, NPVariant *variant) {
87 size_t length = in.size();
88 NPUTF8 *chars = static_cast<NPUTF8 *>(malloc(length));
89 if (!chars) {
90 VOID_TO_NPVARIANT(*variant);
91 return false;
92 }
93 memcpy(chars, in.c_str(), length);
94 STRINGN_TO_NPVARIANT(chars, length, *variant);
95 return true;
96 }
97
98 //------------------------------------------------------------------------------
99 // Implementations of NPClass functions. These are here to:
100 // - Implement postMessage behavior.
101 // - Implement src attribute.
102 //------------------------------------------------------------------------------
103 NPObject* BrowserPluginBindingsAllocate(NPP npp, NPClass* the_class) {
104 return new BrowserPluginBindings::BrowserPluginNPObject;
105 }
106
107 void BrowserPluginBindingsDeallocate(NPObject* object) {
108 BrowserPluginBindings::BrowserPluginNPObject* instance =
109 static_cast<BrowserPluginBindings::BrowserPluginNPObject*>(object);
110 delete instance;
111 }
112
113 bool BrowserPluginBindingsHasMethod(NPObject* np_obj, NPIdentifier name) {
114 if (!np_obj)
115 return false;
116
117 if (IdentifierIsPostMessage(name))
118 return true;
119
120 if (IdentifierIsAddEventListener(name))
121 return true;
122
123 if (IdentifierIsRemoveEventListener(name))
124 return true;
125
126 return false;
127 }
128
129 bool BrowserPluginBindingsInvoke(NPObject* np_obj, NPIdentifier name,
130 const NPVariant* args, uint32 arg_count,
131 NPVariant* result) {
132 if (!np_obj)
133 return false;
134
135 BrowserPluginBindings* bindings = GetBindings(np_obj);
136 if (!bindings)
137 return false;
138
139 if (IdentifierIsPostMessage(name) && (arg_count == 2)) {
Charlie Reis 2012/08/03 18:06:02 Is this a typical pattern for bindings classes, or
Fady Samuel 2012/08/03 19:34:43 I agree, this will grow long fairly quickly as the
140 v8::Handle<v8::Value> v8_val = WebBindings::toV8Value(&args[0]);
141 // If serialization fails, there may be a V8 exception pending.
142 // Don't touch the V8 state (eg, to raise our own 'error calling
143 // method on NPObject' exception).
144 if (v8_val.IsEmpty())
145 // This might happen if toV8Value fails an allocation.
146 // Does SafeAllocation::newInstance throw an exception in this case?
147 return true;
148 WebSerializedScriptValue serialized_v8_val =
149 WebSerializedScriptValue::serialize(v8_val);
150 WebString message_string = serialized_v8_val.toString();
151 // Serialization can sometimes fail (the user might try to fax the
152 // |window|, for example); ::serialize will result in a
153 // DATA_CLONE_ERR being raised, but we still need to abort
154 // the postMessage() operation. There's no clear way to test
155 // for failure in WebSerializedScriptValue, but an empty string
156 // should signal an invalid object. (The serializer at a nonzero
157 // version will always write a version tag.)
158 // v8::TryCatch, for some reason, was not catching DATA_CLONE_ERR;
159 // if this worked, it would be the right way to go.
160 // (This isn't the only way that serialization might fail! Other
161 // exceptions are possible.)
162 if (!message_string.length())
163 return true;
164 string16 message(message_string);
165 string16 target_origin = String16FromNPVariant(args[1]);
166 bindings->instance()->PostMessage(message, target_origin);
Charlie Reis 2012/08/03 18:06:02 Just to confirm my understanding, this allows JS c
Fady Samuel 2012/08/03 19:34:43 That is correct.
167 return true;
168 }
169
170 if (IdentifierIsAddEventListener(name) && (arg_count == 2)) {
171 std::string event_name = StringFromNPVariant(args[0]);
172 if (event_name.empty())
173 return false;
174
175 v8::Local<v8::Value> value =
176 v8::Local<v8::Value>::New(WebBindings::toV8Value(&args[1]));
177 if (value.IsEmpty() || !value->IsFunction())
178 return false;
179
180 v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(value);
181 return bindings->instance()->AddEventListener(event_name, function);
182 }
183
184 if (IdentifierIsRemoveEventListener(name) && arg_count == 2) {
185 std::string event_name = StringFromNPVariant(args[0]);
186 if (event_name.empty())
187 return false;
188
189 v8::Local<v8::Value> value =
190 v8::Local<v8::Value>::New(WebBindings::toV8Value(&args[1]));
191
192 if (value.IsEmpty() || !value->IsFunction())
193 return false;
194
195 v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(value);
196 return bindings->instance()->RemoveEventListener(event_name, function);
197 }
198
199 return false;
200 }
201
202 bool BrowserPluginBindingsInvokeDefault(NPObject* np_obj,
203 const NPVariant* args,
204 uint32 arg_count,
205 NPVariant* result) {
206 NOTIMPLEMENTED();
207 return false;
208 }
209
210 bool BrowserPluginBindingsHasProperty(NPObject* np_obj, NPIdentifier name) {
211 return IdentifierIsSrcAttribute(name);
212 }
213
214 bool BrowserPluginBindingsGetProperty(NPObject* np_obj, NPIdentifier name,
215 NPVariant* result) {
216 if (!np_obj)
217 return false;
218
219 if (IdentifierIsPostMessage(name) ||
220 IdentifierIsAddEventListener(name) ||
221 IdentifierIsRemoveEventListener(name))
222 return false;
223
224 if (IdentifierIsSrcAttribute(name)) {
225 BrowserPluginBindings* bindings = GetBindings(np_obj);
226 if (!bindings)
227 return false;
228 std::string src = bindings->instance()->GetSrcAttribute();
229 return StringToNPVariant(src, result);
230 }
231
232 return false;
233 }
234
235 bool BrowserPluginBindingsSetProperty(NPObject* np_obj, NPIdentifier name,
236 const NPVariant* variant) {
237 if (!np_obj)
238 return false;
239
240 if (IdentifierIsSrcAttribute(name)) {
241 std::string src = StringFromNPVariant(*variant);
242 BrowserPluginBindings* bindings = GetBindings(np_obj);
243 if (!bindings)
244 return false;
245 bindings->instance()->SetSrcAttribute(src);
246 return true;
247 }
248 return false;
249 }
250
251 bool BrowserPluginBindingsEnumerate(NPObject *np_obj, NPIdentifier **value,
252 uint32_t *count) {
253 NOTIMPLEMENTED();
254 return true;
255 }
256
257 NPClass browser_plugin_message_class = {
258 NP_CLASS_STRUCT_VERSION,
259 &BrowserPluginBindingsAllocate,
260 &BrowserPluginBindingsDeallocate,
261 NULL,
262 &BrowserPluginBindingsHasMethod,
263 &BrowserPluginBindingsInvoke,
264 &BrowserPluginBindingsInvokeDefault,
265 &BrowserPluginBindingsHasProperty,
266 &BrowserPluginBindingsGetProperty,
267 &BrowserPluginBindingsSetProperty,
268 NULL,
269 &BrowserPluginBindingsEnumerate,
270 };
271
272 } // namespace
273
274 // BrowserPluginBindings ------------------------------------------------------
275
276 BrowserPluginBindings::BrowserPluginNPObject::BrowserPluginNPObject() {
277 }
278
279 BrowserPluginBindings::BrowserPluginNPObject::~BrowserPluginNPObject() {
280 }
281
282 BrowserPluginBindings::BrowserPluginBindings(BrowserPlugin* instance)
283 : instance_(instance),
284 np_object_(NULL),
285 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
286 NPObject* obj =
287 WebBindings::createObject(NULL, &browser_plugin_message_class);
288 np_object_ = static_cast<BrowserPluginBindings::BrowserPluginNPObject*>(obj);
289 np_object_->message_channel = weak_ptr_factory_.GetWeakPtr();
290 }
291
292 BrowserPluginBindings::~BrowserPluginBindings() {
293 WebBindings::releaseObject(np_object_);
294 }
295
296 } // namespace browser_plugin
297 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698