OLD | NEW |
| (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/child/npapi/plugin_host.h" | |
6 | |
7 #include <stddef.h> | |
8 #include <string.h> | |
9 | |
10 #include "base/command_line.h" | |
11 #include "base/files/file_util.h" | |
12 #include "base/lazy_instance.h" | |
13 #include "base/logging.h" | |
14 #include "base/memory/scoped_ptr.h" | |
15 #include "base/strings/string_piece.h" | |
16 #include "base/strings/string_util.h" | |
17 #include "base/strings/sys_string_conversions.h" | |
18 #include "base/strings/utf_string_conversions.h" | |
19 #include "build/build_config.h" | |
20 #include "content/child/npapi/plugin_instance.h" | |
21 #include "content/child/npapi/plugin_lib.h" | |
22 #include "content/child/npapi/webplugin_delegate.h" | |
23 #include "content/public/common/content_client.h" | |
24 #include "content/public/common/content_switches.h" | |
25 #include "content/public/common/user_agent.h" | |
26 #include "content/public/common/webplugininfo.h" | |
27 #include "net/base/filename_util.h" | |
28 #include "third_party/WebKit/public/web/WebBindings.h" | |
29 #include "third_party/WebKit/public/web/WebKit.h" | |
30 #include "third_party/npapi/bindings/npruntime.h" | |
31 #include "ui/gl/gl_implementation.h" | |
32 #include "ui/gl/gl_surface.h" | |
33 | |
34 using blink::WebBindings; | |
35 | |
36 // Declarations for stub implementations of deprecated functions, which are no | |
37 // longer listed in npapi.h. | |
38 extern "C" { | |
39 void* NPN_GetJavaEnv(); | |
40 void* NPN_GetJavaPeer(NPP); | |
41 } | |
42 | |
43 namespace content { | |
44 | |
45 // Finds a PluginInstance from an NPP. | |
46 // The caller must take a reference if needed. | |
47 static PluginInstance* FindInstance(NPP id) { | |
48 if (id == NULL) { | |
49 return NULL; | |
50 } | |
51 return reinterpret_cast<PluginInstance*>(id->ndata); | |
52 } | |
53 | |
54 #if defined(OS_MACOSX) | |
55 // Returns true if Core Animation plugins are supported. This requires that the | |
56 // OS supports shared accelerated surfaces via IOSurface. This is true on Snow | |
57 // Leopard and higher. | |
58 static bool SupportsCoreAnimationPlugins() { | |
59 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | |
60 switches::kDisableCoreAnimationPlugins)) | |
61 return false; | |
62 // We also need to be running with desktop GL and not the software | |
63 // OSMesa renderer in order to share accelerated surfaces between | |
64 // processes. Because on MacOS we lazy-initialize GLSurface in the | |
65 // renderer process here, ensure we're not also initializing GL somewhere | |
66 // else, and that we only do this once. | |
67 static gfx::GLImplementation implementation = gfx::kGLImplementationNone; | |
68 if (implementation == gfx::kGLImplementationNone) { | |
69 // Not initialized yet. | |
70 DCHECK_EQ(implementation, gfx::GetGLImplementation()) | |
71 << "GL already initialized by someone else to: " | |
72 << gfx::GetGLImplementation(); | |
73 if (!gfx::GLSurface::InitializeOneOff()) { | |
74 return false; | |
75 } | |
76 implementation = gfx::GetGLImplementation(); | |
77 } | |
78 return (implementation == gfx::kGLImplementationDesktopGL); | |
79 } | |
80 #endif | |
81 | |
82 PluginHost::PluginHost() { | |
83 InitializeHostFuncs(); | |
84 } | |
85 | |
86 PluginHost::~PluginHost() { | |
87 } | |
88 | |
89 PluginHost *PluginHost::Singleton() { | |
90 CR_DEFINE_STATIC_LOCAL(scoped_refptr<PluginHost>, singleton, ()); | |
91 if (singleton.get() == NULL) { | |
92 singleton = new PluginHost(); | |
93 } | |
94 | |
95 DCHECK(singleton.get() != NULL); | |
96 return singleton.get(); | |
97 } | |
98 | |
99 void PluginHost::InitializeHostFuncs() { | |
100 memset(&host_funcs_, 0, sizeof(host_funcs_)); | |
101 host_funcs_.size = sizeof(host_funcs_); | |
102 host_funcs_.version = (NP_VERSION_MAJOR << 8) | (NP_VERSION_MINOR); | |
103 | |
104 // The "basic" functions | |
105 host_funcs_.geturl = &NPN_GetURL; | |
106 host_funcs_.posturl = &NPN_PostURL; | |
107 host_funcs_.requestread = &NPN_RequestRead; | |
108 host_funcs_.newstream = &NPN_NewStream; | |
109 host_funcs_.write = &NPN_Write; | |
110 host_funcs_.destroystream = &NPN_DestroyStream; | |
111 host_funcs_.status = &NPN_Status; | |
112 host_funcs_.uagent = &NPN_UserAgent; | |
113 host_funcs_.memalloc = &NPN_MemAlloc; | |
114 host_funcs_.memfree = &NPN_MemFree; | |
115 host_funcs_.memflush = &NPN_MemFlush; | |
116 host_funcs_.reloadplugins = &NPN_ReloadPlugins; | |
117 | |
118 // Stubs for deprecated Java functions | |
119 host_funcs_.getJavaEnv = &NPN_GetJavaEnv; | |
120 host_funcs_.getJavaPeer = &NPN_GetJavaPeer; | |
121 | |
122 // Advanced functions we implement | |
123 host_funcs_.geturlnotify = &NPN_GetURLNotify; | |
124 host_funcs_.posturlnotify = &NPN_PostURLNotify; | |
125 host_funcs_.getvalue = &NPN_GetValue; | |
126 host_funcs_.setvalue = &NPN_SetValue; | |
127 host_funcs_.invalidaterect = &NPN_InvalidateRect; | |
128 host_funcs_.invalidateregion = &NPN_InvalidateRegion; | |
129 host_funcs_.forceredraw = &NPN_ForceRedraw; | |
130 | |
131 // These come from the Javascript Engine | |
132 host_funcs_.getstringidentifier = WebBindings::getStringIdentifier; | |
133 host_funcs_.getstringidentifiers = WebBindings::getStringIdentifiers; | |
134 host_funcs_.getintidentifier = WebBindings::getIntIdentifier; | |
135 host_funcs_.identifierisstring = WebBindings::identifierIsString; | |
136 host_funcs_.utf8fromidentifier = WebBindings::utf8FromIdentifier; | |
137 host_funcs_.intfromidentifier = WebBindings::intFromIdentifier; | |
138 host_funcs_.createobject = WebBindings::createObject; | |
139 host_funcs_.retainobject = WebBindings::retainObject; | |
140 host_funcs_.releaseobject = WebBindings::releaseObject; | |
141 host_funcs_.invoke = WebBindings::invoke; | |
142 host_funcs_.invokeDefault = WebBindings::invokeDefault; | |
143 host_funcs_.evaluate = WebBindings::evaluate; | |
144 host_funcs_.getproperty = WebBindings::getProperty; | |
145 host_funcs_.setproperty = WebBindings::setProperty; | |
146 host_funcs_.removeproperty = WebBindings::removeProperty; | |
147 host_funcs_.hasproperty = WebBindings::hasProperty; | |
148 host_funcs_.hasmethod = WebBindings::hasMethod; | |
149 host_funcs_.releasevariantvalue = WebBindings::releaseVariantValue; | |
150 host_funcs_.setexception = WebBindings::setException; | |
151 host_funcs_.pushpopupsenabledstate = NPN_PushPopupsEnabledState; | |
152 host_funcs_.poppopupsenabledstate = NPN_PopPopupsEnabledState; | |
153 host_funcs_.enumerate = WebBindings::enumerate; | |
154 host_funcs_.pluginthreadasynccall = NPN_PluginThreadAsyncCall; | |
155 host_funcs_.construct = WebBindings::construct; | |
156 host_funcs_.getvalueforurl = NPN_GetValueForURL; | |
157 host_funcs_.setvalueforurl = NPN_SetValueForURL; | |
158 host_funcs_.getauthenticationinfo = NPN_GetAuthenticationInfo; | |
159 host_funcs_.scheduletimer = NPN_ScheduleTimer; | |
160 host_funcs_.unscheduletimer = NPN_UnscheduleTimer; | |
161 host_funcs_.popupcontextmenu = NPN_PopUpContextMenu; | |
162 host_funcs_.convertpoint = NPN_ConvertPoint; | |
163 host_funcs_.handleevent = NPN_HandleEvent; | |
164 host_funcs_.unfocusinstance = NPN_UnfocusInstance; | |
165 host_funcs_.urlredirectresponse = NPN_URLRedirectResponse; | |
166 } | |
167 | |
168 void PluginHost::PatchNPNetscapeFuncs(NPNetscapeFuncs* overrides) { | |
169 // When running in the plugin process, we need to patch the NPN functions | |
170 // that the plugin calls to interact with NPObjects that we give. Otherwise | |
171 // the plugin will call the v8 NPN functions, which won't work since we have | |
172 // an NPObjectProxy and not a real v8 implementation. | |
173 if (overrides->invoke) | |
174 host_funcs_.invoke = overrides->invoke; | |
175 | |
176 if (overrides->invokeDefault) | |
177 host_funcs_.invokeDefault = overrides->invokeDefault; | |
178 | |
179 if (overrides->evaluate) | |
180 host_funcs_.evaluate = overrides->evaluate; | |
181 | |
182 if (overrides->getproperty) | |
183 host_funcs_.getproperty = overrides->getproperty; | |
184 | |
185 if (overrides->setproperty) | |
186 host_funcs_.setproperty = overrides->setproperty; | |
187 | |
188 if (overrides->removeproperty) | |
189 host_funcs_.removeproperty = overrides->removeproperty; | |
190 | |
191 if (overrides->hasproperty) | |
192 host_funcs_.hasproperty = overrides->hasproperty; | |
193 | |
194 if (overrides->hasmethod) | |
195 host_funcs_.hasmethod = overrides->hasmethod; | |
196 | |
197 if (overrides->setexception) | |
198 host_funcs_.setexception = overrides->setexception; | |
199 | |
200 if (overrides->enumerate) | |
201 host_funcs_.enumerate = overrides->enumerate; | |
202 } | |
203 | |
204 bool PluginHost::SetPostData(const char* buf, | |
205 uint32_t length, | |
206 std::vector<std::string>* names, | |
207 std::vector<std::string>* values, | |
208 std::vector<char>* body) { | |
209 // Use a state table to do the parsing. Whitespace must be | |
210 // trimmed after the fact if desired. In our case, we actually | |
211 // don't care about the whitespace, because we're just going to | |
212 // pass this back into another POST. This function strips out the | |
213 // "Content-length" header and does not append it to the request. | |
214 | |
215 // | |
216 // This parser takes action only on state changes. | |
217 // | |
218 // Transition table: | |
219 // : \n NULL Other | |
220 // 0 GetHeader 1 2 4 0 | |
221 // 1 GetValue 1 0 3 1 | |
222 // 2 GetData 2 2 3 2 | |
223 // 3 DONE | |
224 // 4 ERR | |
225 // | |
226 enum { INPUT_COLON=0, INPUT_NEWLINE, INPUT_NULL, INPUT_OTHER }; | |
227 enum { GETNAME, GETVALUE, GETDATA, DONE, ERR }; | |
228 int statemachine[3][4] = { { GETVALUE, GETDATA, GETDATA, GETNAME }, | |
229 { GETVALUE, GETNAME, DONE, GETVALUE }, | |
230 { GETDATA, GETDATA, DONE, GETDATA } }; | |
231 std::string name, value; | |
232 const char* ptr = static_cast<const char*>(buf); | |
233 const char* start = ptr; | |
234 int state = GETNAME; // initial state | |
235 bool done = false; | |
236 bool err = false; | |
237 do { | |
238 int input; | |
239 | |
240 // Translate the current character into an input | |
241 // for the state table. | |
242 switch (*ptr) { | |
243 case ':' : | |
244 input = INPUT_COLON; | |
245 break; | |
246 case '\n': | |
247 input = INPUT_NEWLINE; | |
248 break; | |
249 case 0 : | |
250 input = INPUT_NULL; | |
251 break; | |
252 default : | |
253 input = INPUT_OTHER; | |
254 break; | |
255 } | |
256 | |
257 int newstate = statemachine[state][input]; | |
258 | |
259 // Take action based on the new state. | |
260 if (state != newstate) { | |
261 switch (newstate) { | |
262 case GETNAME: | |
263 // Got a value. | |
264 value = std::string(start, ptr - start); | |
265 base::TrimWhitespaceASCII(value, base::TRIM_ALL, &value); | |
266 // If the name field is empty, we'll skip this header | |
267 // but we won't error out. | |
268 if (!name.empty() && name != "content-length") { | |
269 names->push_back(name); | |
270 values->push_back(value); | |
271 } | |
272 start = ptr + 1; | |
273 break; | |
274 case GETVALUE: | |
275 // Got a header. | |
276 name = base::ToLowerASCII(base::StringPiece(start, ptr - start)); | |
277 base::TrimWhitespaceASCII(name, base::TRIM_ALL, &name); | |
278 start = ptr + 1; | |
279 break; | |
280 case GETDATA: { | |
281 // Finished headers, now get body | |
282 if (*ptr) | |
283 start = ptr + 1; | |
284 size_t previous_size = body->size(); | |
285 size_t new_body_size = length - static_cast<int>(start - buf); | |
286 body->resize(previous_size + new_body_size); | |
287 if (!body->empty()) | |
288 memcpy(&body->front() + previous_size, start, new_body_size); | |
289 done = true; | |
290 break; | |
291 } | |
292 case ERR: | |
293 // error | |
294 err = true; | |
295 done = true; | |
296 break; | |
297 } | |
298 } | |
299 state = newstate; | |
300 ptr++; | |
301 } while (!done); | |
302 | |
303 return !err; | |
304 } | |
305 | |
306 } // namespace content | |
307 | |
308 extern "C" { | |
309 | |
310 using content::FindInstance; | |
311 using content::PluginHost; | |
312 using content::PluginInstance; | |
313 using content::WebPlugin; | |
314 | |
315 // Allocates memory from the host's memory space. | |
316 void* NPN_MemAlloc(uint32_t size) { | |
317 // Note: We must use the same allocator/deallocator | |
318 // that is used by the javascript library, as some of the | |
319 // JS APIs will pass memory to the plugin which the plugin | |
320 // will attempt to free. | |
321 return malloc(size); | |
322 } | |
323 | |
324 // Deallocates memory from the host's memory space | |
325 void NPN_MemFree(void* ptr) { | |
326 if (ptr != NULL && ptr != reinterpret_cast<void*>(-1)) | |
327 free(ptr); | |
328 } | |
329 | |
330 // Requests that the host free a specified amount of memory. | |
331 uint32_t NPN_MemFlush(uint32_t size) { | |
332 // This is not relevant on Windows; MAC specific | |
333 return size; | |
334 } | |
335 | |
336 // This is for dynamic discovery of new plugins. | |
337 // Should force a re-scan of the plugins directory to load new ones. | |
338 void NPN_ReloadPlugins(NPBool reload_pages) { | |
339 blink::resetPluginCache(reload_pages ? true : false); | |
340 } | |
341 | |
342 // Requests a range of bytes for a seekable stream. | |
343 NPError NPN_RequestRead(NPStream* stream, NPByteRange* range_list) { | |
344 return NPERR_GENERIC_ERROR; | |
345 } | |
346 | |
347 NPError NPN_GetURLNotify(NPP id, | |
348 const char* url, | |
349 const char* target, | |
350 void* notify_data) { | |
351 return NPERR_GENERIC_ERROR; | |
352 } | |
353 | |
354 NPError NPN_GetURL(NPP id, const char* url, const char* target) { | |
355 return NPERR_GENERIC_ERROR; | |
356 } | |
357 | |
358 NPError NPN_PostURLNotify(NPP id, | |
359 const char* url, | |
360 const char* target, | |
361 uint32_t len, | |
362 const char* buf, | |
363 NPBool file, | |
364 void* notify_data) { | |
365 return NPERR_GENERIC_ERROR; | |
366 } | |
367 | |
368 NPError NPN_PostURL(NPP id, | |
369 const char* url, | |
370 const char* target, | |
371 uint32_t len, | |
372 const char* buf, | |
373 NPBool file) { | |
374 return NPERR_GENERIC_ERROR; | |
375 } | |
376 | |
377 NPError NPN_NewStream(NPP id, | |
378 NPMIMEType type, | |
379 const char* target, | |
380 NPStream** stream) { | |
381 // Requests creation of a new data stream produced by the plugin, | |
382 // consumed by the browser. | |
383 // | |
384 // Browser should put this stream into a window target. | |
385 // | |
386 // TODO: implement me | |
387 DVLOG(1) << "NPN_NewStream is not implemented yet."; | |
388 return NPERR_GENERIC_ERROR; | |
389 } | |
390 | |
391 int32_t NPN_Write(NPP id, NPStream* stream, int32_t len, void* buffer) { | |
392 // Writes data to an existing Plugin-created stream. | |
393 | |
394 // TODO: implement me | |
395 DVLOG(1) << "NPN_Write is not implemented yet."; | |
396 return NPERR_GENERIC_ERROR; | |
397 } | |
398 | |
399 NPError NPN_DestroyStream(NPP id, NPStream* stream, NPReason reason) { | |
400 // Destroys a stream (could be created by plugin or browser). | |
401 // | |
402 // Reasons: | |
403 // NPRES_DONE - normal completion | |
404 // NPRES_USER_BREAK - user terminated | |
405 // NPRES_NETWORK_ERROR - network error (all errors fit here?) | |
406 // | |
407 // | |
408 | |
409 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
410 if (plugin.get() == NULL) { | |
411 NOTREACHED(); | |
412 return NPERR_GENERIC_ERROR; | |
413 } | |
414 | |
415 return plugin->NPP_DestroyStream(stream, reason); | |
416 } | |
417 | |
418 const char* NPN_UserAgent(NPP id) { | |
419 #if defined(OS_WIN) | |
420 // Flash passes in a null id during the NP_initialize call. We need to | |
421 // default to the Mozilla user agent if we don't have an NPP instance or | |
422 // else Flash won't request windowless mode. | |
423 bool use_mozilla_user_agent = true; | |
424 if (id) { | |
425 scoped_refptr<PluginInstance> plugin = FindInstance(id); | |
426 if (plugin.get() && !plugin->use_mozilla_user_agent()) | |
427 use_mozilla_user_agent = false; | |
428 } | |
429 | |
430 if (use_mozilla_user_agent) | |
431 return "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9a1) " | |
432 "Gecko/20061103 Firefox/2.0a1"; | |
433 #endif | |
434 | |
435 // Provide a consistent user-agent string with memory that lasts | |
436 // long enough for the caller to read it. | |
437 static base::LazyInstance<std::string>::Leaky leaky_user_agent = | |
438 LAZY_INSTANCE_INITIALIZER; | |
439 if (leaky_user_agent == NULL) | |
440 leaky_user_agent.Get() = content::GetContentClient()->GetUserAgent(); | |
441 return leaky_user_agent.Get().c_str(); | |
442 } | |
443 | |
444 void NPN_Status(NPP id, const char* message) { | |
445 // Displays a message on the status line of the browser window. | |
446 | |
447 // TODO: implement me | |
448 DVLOG(1) << "NPN_Status is not implemented yet."; | |
449 } | |
450 | |
451 void NPN_InvalidateRect(NPP id, NPRect *invalidRect) { | |
452 // Invalidates specified drawing area prior to repainting or refreshing a | |
453 // windowless plugin | |
454 | |
455 // Before a windowless plugin can refresh part of its drawing area, it must | |
456 // first invalidate it. This function causes the NPP_HandleEvent method to | |
457 // pass an update event or a paint message to the plugin. After calling | |
458 // this method, the plugin receives a paint message asynchronously. | |
459 | |
460 // The browser redraws invalid areas of the document and any windowless | |
461 // plugins at regularly timed intervals. To force a paint message, the | |
462 // plugin can call NPN_ForceRedraw after calling this method. | |
463 | |
464 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
465 if (plugin.get() && plugin->webplugin()) { | |
466 if (invalidRect) { | |
467 gfx::Rect rect(invalidRect->left, | |
468 invalidRect->top, | |
469 invalidRect->right - invalidRect->left, | |
470 invalidRect->bottom - invalidRect->top); | |
471 plugin->webplugin()->InvalidateRect(rect); | |
472 } else { | |
473 plugin->webplugin()->Invalidate(); | |
474 } | |
475 } | |
476 } | |
477 | |
478 void NPN_InvalidateRegion(NPP id, NPRegion invalidRegion) { | |
479 // Invalidates a specified drawing region prior to repainting | |
480 // or refreshing a window-less plugin. | |
481 // | |
482 // Similar to NPN_InvalidateRect. | |
483 | |
484 // TODO: this is overkill--add platform-specific region handling (at the | |
485 // very least, fetch the region's bounding box and pass it to InvalidateRect). | |
486 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
487 DCHECK(plugin.get() != NULL); | |
488 if (plugin.get() && plugin->webplugin()) | |
489 plugin->webplugin()->Invalidate(); | |
490 } | |
491 | |
492 void NPN_ForceRedraw(NPP id) { | |
493 // Forces repaint for a windowless plugin. | |
494 // | |
495 // We deliberately do not implement this; we don't want plugins forcing | |
496 // synchronous paints. | |
497 } | |
498 | |
499 NPError NPN_GetValue(NPP id, NPNVariable variable, void* value) { | |
500 // Allows the plugin to query the browser for information | |
501 // | |
502 // Variables: | |
503 // NPNVxDisplay (unix only) | |
504 // NPNVxtAppContext (unix only) | |
505 // NPNVjavascriptEnabledBool: tells whether Javascript is enabled | |
506 // NPNVasdEnabledBool: tells whether SmartUpdate is enabled | |
507 // NPNVOfflineBool: tells whether offline-mode is enabled | |
508 | |
509 NPError rv = NPERR_GENERIC_ERROR; | |
510 | |
511 switch (static_cast<int>(variable)) { | |
512 case NPNVjavascriptEnabledBool: { | |
513 // yes, JS is enabled. | |
514 *((void**)value) = (void*)1; | |
515 rv = NPERR_NO_ERROR; | |
516 break; | |
517 } | |
518 case NPNVSupportsWindowless: { | |
519 NPBool* supports_windowless = reinterpret_cast<NPBool*>(value); | |
520 *supports_windowless = true; | |
521 rv = NPERR_NO_ERROR; | |
522 break; | |
523 } | |
524 case NPNVprivateModeBool: { | |
525 NPBool* private_mode = reinterpret_cast<NPBool*>(value); | |
526 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
527 if (!plugin.get()) { | |
528 NOTREACHED(); | |
529 return NPERR_INVALID_INSTANCE_ERROR; | |
530 } | |
531 *private_mode = plugin->webplugin()->IsOffTheRecord(); | |
532 rv = NPERR_NO_ERROR; | |
533 break; | |
534 } | |
535 #if defined(OS_MACOSX) | |
536 case NPNVpluginDrawingModel: { | |
537 // return the drawing model that was negotiated when we initialized. | |
538 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
539 if (!plugin.get()) { | |
540 NOTREACHED(); | |
541 return NPERR_INVALID_INSTANCE_ERROR; | |
542 } | |
543 *reinterpret_cast<int*>(value) = plugin->drawing_model(); | |
544 rv = NPERR_NO_ERROR; | |
545 break; | |
546 } | |
547 case NPNVsupportsCoreGraphicsBool: | |
548 case NPNVsupportsCocoaBool: { | |
549 // These drawing and event models are always supported. | |
550 NPBool* supports_model = reinterpret_cast<NPBool*>(value); | |
551 *supports_model = true; | |
552 rv = NPERR_NO_ERROR; | |
553 break; | |
554 } | |
555 case NPNVsupportsInvalidatingCoreAnimationBool: | |
556 case NPNVsupportsCoreAnimationBool: { | |
557 NPBool* supports_model = reinterpret_cast<NPBool*>(value); | |
558 *supports_model = content::SupportsCoreAnimationPlugins(); | |
559 rv = NPERR_NO_ERROR; | |
560 break; | |
561 } | |
562 #ifndef NP_NO_CARBON | |
563 case NPNVsupportsCarbonBool: | |
564 #endif | |
565 #ifndef NP_NO_QUICKDRAW | |
566 case NPNVsupportsQuickDrawBool: | |
567 #endif | |
568 case NPNVsupportsOpenGLBool: { | |
569 // These models are never supported. OpenGL was never widely supported, | |
570 // and QuickDraw and Carbon have been deprecated for quite some time. | |
571 NPBool* supports_model = reinterpret_cast<NPBool*>(value); | |
572 *supports_model = false; | |
573 rv = NPERR_NO_ERROR; | |
574 break; | |
575 } | |
576 case NPNVsupportsCompositingCoreAnimationPluginsBool: { | |
577 NPBool* supports_compositing = reinterpret_cast<NPBool*>(value); | |
578 *supports_compositing = content::SupportsCoreAnimationPlugins(); | |
579 rv = NPERR_NO_ERROR; | |
580 break; | |
581 } | |
582 case NPNVsupportsUpdatedCocoaTextInputBool: { | |
583 // We support the clarifications to the Cocoa IME event spec. | |
584 NPBool* supports_update = reinterpret_cast<NPBool*>(value); | |
585 *supports_update = true; | |
586 rv = NPERR_NO_ERROR; | |
587 break; | |
588 } | |
589 #endif // OS_MACOSX | |
590 default: | |
591 DVLOG(1) << "NPN_GetValue(" << variable << ") is not implemented yet."; | |
592 break; | |
593 } | |
594 return rv; | |
595 } | |
596 | |
597 NPError NPN_SetValue(NPP id, NPPVariable variable, void* value) { | |
598 // Allows the plugin to set various modes | |
599 | |
600 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
601 if (!plugin.get()) { | |
602 NOTREACHED(); | |
603 return NPERR_INVALID_INSTANCE_ERROR; | |
604 } | |
605 switch(variable) { | |
606 case NPPVpluginTransparentBool: { | |
607 // Sets transparent mode for display of the plugin | |
608 // | |
609 // Transparent plugins require the browser to paint the background | |
610 // before having the plugin paint. By default, windowless plugins | |
611 // are transparent. Making a windowless plugin opaque means that | |
612 // the plugin does not require the browser to paint the background. | |
613 bool mode = (value != 0); | |
614 plugin->set_transparent(mode); | |
615 return NPERR_NO_ERROR; | |
616 } | |
617 case NPPVjavascriptPushCallerBool: | |
618 // Specifies whether you are pushing or popping the JSContext off. | |
619 // the stack | |
620 // TODO: implement me | |
621 DVLOG(1) << "NPN_SetValue(NPPVJavascriptPushCallerBool) is not " | |
622 "implemented."; | |
623 return NPERR_GENERIC_ERROR; | |
624 case NPPVpluginKeepLibraryInMemory: | |
625 // Tells browser that plugin library should live longer than usual. | |
626 // TODO: implement me | |
627 DVLOG(1) << "NPN_SetValue(NPPVpluginKeepLibraryInMemory) is not " | |
628 "implemented."; | |
629 return NPERR_GENERIC_ERROR; | |
630 #if defined(OS_MACOSX) | |
631 case NPPVpluginDrawingModel: { | |
632 intptr_t model = reinterpret_cast<intptr_t>(value); | |
633 if (model == NPDrawingModelCoreGraphics || | |
634 ((model == NPDrawingModelInvalidatingCoreAnimation || | |
635 model == NPDrawingModelCoreAnimation) && | |
636 content::SupportsCoreAnimationPlugins())) { | |
637 plugin->set_drawing_model(static_cast<NPDrawingModel>(model)); | |
638 return NPERR_NO_ERROR; | |
639 } | |
640 return NPERR_GENERIC_ERROR; | |
641 } | |
642 case NPPVpluginEventModel: { | |
643 // Only the Cocoa event model is supported. | |
644 intptr_t model = reinterpret_cast<intptr_t>(value); | |
645 if (model == NPEventModelCocoa) { | |
646 plugin->set_event_model(static_cast<NPEventModel>(model)); | |
647 return NPERR_NO_ERROR; | |
648 } | |
649 return NPERR_GENERIC_ERROR; | |
650 } | |
651 #endif | |
652 default: | |
653 // TODO: implement me | |
654 DVLOG(1) << "NPN_SetValue(" << variable << ") is not implemented."; | |
655 break; | |
656 } | |
657 | |
658 NOTREACHED(); | |
659 return NPERR_GENERIC_ERROR; | |
660 } | |
661 | |
662 void* NPN_GetJavaEnv() { | |
663 // TODO: implement me | |
664 DVLOG(1) << "NPN_GetJavaEnv is not implemented."; | |
665 return NULL; | |
666 } | |
667 | |
668 void* NPN_GetJavaPeer(NPP) { | |
669 // TODO: implement me | |
670 DVLOG(1) << "NPN_GetJavaPeer is not implemented."; | |
671 return NULL; | |
672 } | |
673 | |
674 void NPN_PushPopupsEnabledState(NPP id, NPBool enabled) { | |
675 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
676 if (plugin.get()) | |
677 plugin->PushPopupsEnabledState(enabled ? true : false); | |
678 } | |
679 | |
680 void NPN_PopPopupsEnabledState(NPP id) { | |
681 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
682 if (plugin.get()) | |
683 plugin->PopPopupsEnabledState(); | |
684 } | |
685 | |
686 void NPN_PluginThreadAsyncCall(NPP id, | |
687 void (*func)(void*), | |
688 void* user_data) { | |
689 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
690 if (plugin.get()) | |
691 plugin->PluginThreadAsyncCall(func, user_data); | |
692 } | |
693 | |
694 NPError NPN_GetValueForURL(NPP id, | |
695 NPNURLVariable variable, | |
696 const char* url, | |
697 char** value, | |
698 uint32_t* len) { | |
699 if (!id) | |
700 return NPERR_INVALID_PARAM; | |
701 | |
702 if (!url || !*url || !len) | |
703 return NPERR_INVALID_URL; | |
704 | |
705 *len = 0; | |
706 std::string result; | |
707 | |
708 switch (variable) { | |
709 case NPNURLVProxy: { | |
710 result = "DIRECT"; | |
711 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
712 if (!plugin.get()) | |
713 return NPERR_GENERIC_ERROR; | |
714 | |
715 WebPlugin* webplugin = plugin->webplugin(); | |
716 if (!webplugin) | |
717 return NPERR_GENERIC_ERROR; | |
718 | |
719 if (!webplugin->FindProxyForUrl(GURL(std::string(url)), &result)) | |
720 return NPERR_GENERIC_ERROR; | |
721 break; | |
722 } | |
723 case NPNURLVCookie: { | |
724 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
725 if (!plugin.get()) | |
726 return NPERR_GENERIC_ERROR; | |
727 | |
728 WebPlugin* webplugin = plugin->webplugin(); | |
729 if (!webplugin) | |
730 return NPERR_GENERIC_ERROR; | |
731 | |
732 // Bypass third-party cookie blocking by using the url as the | |
733 // first_party_for_cookies. | |
734 GURL cookies_url((std::string(url))); | |
735 result = webplugin->GetCookies(cookies_url, cookies_url); | |
736 break; | |
737 } | |
738 default: | |
739 return NPERR_GENERIC_ERROR; | |
740 } | |
741 | |
742 // Allocate this using the NPAPI allocator. The plugin will call | |
743 // NPN_Free to free this. | |
744 *value = static_cast<char*>(NPN_MemAlloc(result.length() + 1)); | |
745 base::strlcpy(*value, result.c_str(), result.length() + 1); | |
746 *len = result.length(); | |
747 | |
748 return NPERR_NO_ERROR; | |
749 } | |
750 | |
751 NPError NPN_SetValueForURL(NPP id, | |
752 NPNURLVariable variable, | |
753 const char* url, | |
754 const char* value, | |
755 uint32_t len) { | |
756 if (!id) | |
757 return NPERR_INVALID_PARAM; | |
758 | |
759 if (!url || !*url) | |
760 return NPERR_INVALID_URL; | |
761 | |
762 switch (variable) { | |
763 case NPNURLVCookie: { | |
764 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
765 if (!plugin.get()) | |
766 return NPERR_GENERIC_ERROR; | |
767 | |
768 WebPlugin* webplugin = plugin->webplugin(); | |
769 if (!webplugin) | |
770 return NPERR_GENERIC_ERROR; | |
771 | |
772 std::string cookie(value, len); | |
773 GURL cookies_url((std::string(url))); | |
774 webplugin->SetCookie(cookies_url, cookies_url, cookie); | |
775 return NPERR_NO_ERROR; | |
776 } | |
777 case NPNURLVProxy: | |
778 // We don't support setting proxy values, fall through... | |
779 break; | |
780 default: | |
781 // Fall through and return an error... | |
782 break; | |
783 } | |
784 | |
785 return NPERR_GENERIC_ERROR; | |
786 } | |
787 | |
788 NPError NPN_GetAuthenticationInfo(NPP id, | |
789 const char* protocol, | |
790 const char* host, | |
791 int32_t port, | |
792 const char* scheme, | |
793 const char* realm, | |
794 char** username, | |
795 uint32_t* ulen, | |
796 char** password, | |
797 uint32_t* plen) { | |
798 if (!id || !protocol || !host || !scheme || !realm || !username || | |
799 !ulen || !password || !plen) | |
800 return NPERR_INVALID_PARAM; | |
801 | |
802 // TODO: implement me (bug 23928) | |
803 return NPERR_GENERIC_ERROR; | |
804 } | |
805 | |
806 uint32_t NPN_ScheduleTimer(NPP id, | |
807 uint32_t interval, | |
808 NPBool repeat, | |
809 void (*func)(NPP id, uint32_t timer_id)) { | |
810 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
811 if (!plugin.get()) | |
812 return 0; | |
813 | |
814 return plugin->ScheduleTimer(interval, repeat, func); | |
815 } | |
816 | |
817 void NPN_UnscheduleTimer(NPP id, uint32_t timer_id) { | |
818 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
819 if (plugin.get()) | |
820 plugin->UnscheduleTimer(timer_id); | |
821 } | |
822 | |
823 NPError NPN_PopUpContextMenu(NPP id, NPMenu* menu) { | |
824 if (!menu) | |
825 return NPERR_INVALID_PARAM; | |
826 | |
827 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
828 if (plugin.get()) { | |
829 return plugin->PopUpContextMenu(menu); | |
830 } | |
831 NOTREACHED(); | |
832 return NPERR_GENERIC_ERROR; | |
833 } | |
834 | |
835 NPBool NPN_ConvertPoint(NPP id, double sourceX, double sourceY, | |
836 NPCoordinateSpace sourceSpace, | |
837 double *destX, double *destY, | |
838 NPCoordinateSpace destSpace) { | |
839 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
840 if (plugin.get()) { | |
841 return plugin->ConvertPoint( | |
842 sourceX, sourceY, sourceSpace, destX, destY, destSpace); | |
843 } | |
844 NOTREACHED(); | |
845 return false; | |
846 } | |
847 | |
848 NPBool NPN_HandleEvent(NPP id, void *event, NPBool handled) { | |
849 // TODO: Implement advanced key handling: http://crbug.com/46578 | |
850 NOTIMPLEMENTED(); | |
851 return false; | |
852 } | |
853 | |
854 NPBool NPN_UnfocusInstance(NPP id, NPFocusDirection direction) { | |
855 // TODO: Implement advanced key handling: http://crbug.com/46578 | |
856 NOTIMPLEMENTED(); | |
857 return false; | |
858 } | |
859 | |
860 void NPN_URLRedirectResponse(NPP instance, void* notify_data, NPBool allow) { | |
861 } | |
862 | |
863 } // extern "C" | |
OLD | NEW |