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.
5 #include "content/child/npapi/plugin_host.h"
7 #include "base/command_line.h"
8 #include "base/file_util.h"
9 #include "base/lazy_instance.h"
10 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/strings/string_piece.h"
13 #include "base/strings/string_util.h"
14 #include "base/strings/sys_string_conversions.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "build/build_config.h"
17 #include "content/child/npapi/plugin_instance.h"
18 #include "content/child/npapi/plugin_lib.h"
19 #include "content/child/npapi/plugin_stream_url.h"
20 #include "content/child/npapi/webplugin_delegate.h"
21 #include "content/public/common/content_client.h"
22 #include "content/public/common/content_switches.h"
23 #include "content/public/common/user_agent.h"
24 #include "content/public/common/webplugininfo.h"
25 #include "net/base/filename_util.h"
26 #include "third_party/WebKit/public/web/WebBindings.h"
27 #include "third_party/WebKit/public/web/WebKit.h"
28 #include "third_party/npapi/bindings/npruntime.h"
29 #include "ui/gl/gl_implementation.h"
30 #include "ui/gl/gl_surface.h"
32 #if defined(OS_MACOSX)
33 #include "base/mac/mac_util.h"
36 using blink::WebBindings
;
38 // Declarations for stub implementations of deprecated functions, which are no
39 // longer listed in npapi.h.
41 void* NPN_GetJavaEnv();
42 void* NPN_GetJavaPeer(NPP
);
47 // Finds a PluginInstance from an NPP.
48 // The caller must take a reference if needed.
49 static PluginInstance
* FindInstance(NPP id
) {
53 return reinterpret_cast<PluginInstance
*>(id
->ndata
);
56 #if defined(OS_MACOSX)
57 // Returns true if Core Animation plugins are supported. This requires that the
58 // OS supports shared accelerated surfaces via IOSurface. This is true on Snow
59 // Leopard and higher.
60 static bool SupportsCoreAnimationPlugins() {
61 if (CommandLine::ForCurrentProcess()->HasSwitch(
62 switches::kDisableCoreAnimationPlugins
))
64 // We also need to be running with desktop GL and not the software
65 // OSMesa renderer in order to share accelerated surfaces between
66 // processes. Because on MacOS we lazy-initialize GLSurface in the
67 // renderer process here, ensure we're not also initializing GL somewhere
68 // else, and that we only do this once.
69 static gfx::GLImplementation implementation
= gfx::kGLImplementationNone
;
70 if (implementation
== gfx::kGLImplementationNone
) {
71 // Not initialized yet.
72 DCHECK_EQ(implementation
, gfx::GetGLImplementation())
73 << "GL already initialized by someone else to: "
74 << gfx::GetGLImplementation();
75 if (!gfx::GLSurface::InitializeOneOff()) {
78 implementation
= gfx::GetGLImplementation();
80 return (implementation
== gfx::kGLImplementationDesktopGL
);
84 PluginHost::PluginHost() {
85 InitializeHostFuncs();
88 PluginHost::~PluginHost() {
91 PluginHost
*PluginHost::Singleton() {
92 CR_DEFINE_STATIC_LOCAL(scoped_refptr
<PluginHost
>, singleton
, ());
93 if (singleton
.get() == NULL
) {
94 singleton
= new PluginHost();
97 DCHECK(singleton
.get() != NULL
);
98 return singleton
.get();
101 void PluginHost::InitializeHostFuncs() {
102 memset(&host_funcs_
, 0, sizeof(host_funcs_
));
103 host_funcs_
.size
= sizeof(host_funcs_
);
104 host_funcs_
.version
= (NP_VERSION_MAJOR
<< 8) | (NP_VERSION_MINOR
);
106 // The "basic" functions
107 host_funcs_
.geturl
= &NPN_GetURL
;
108 host_funcs_
.posturl
= &NPN_PostURL
;
109 host_funcs_
.requestread
= &NPN_RequestRead
;
110 host_funcs_
.newstream
= &NPN_NewStream
;
111 host_funcs_
.write
= &NPN_Write
;
112 host_funcs_
.destroystream
= &NPN_DestroyStream
;
113 host_funcs_
.status
= &NPN_Status
;
114 host_funcs_
.uagent
= &NPN_UserAgent
;
115 host_funcs_
.memalloc
= &NPN_MemAlloc
;
116 host_funcs_
.memfree
= &NPN_MemFree
;
117 host_funcs_
.memflush
= &NPN_MemFlush
;
118 host_funcs_
.reloadplugins
= &NPN_ReloadPlugins
;
120 // Stubs for deprecated Java functions
121 host_funcs_
.getJavaEnv
= &NPN_GetJavaEnv
;
122 host_funcs_
.getJavaPeer
= &NPN_GetJavaPeer
;
124 // Advanced functions we implement
125 host_funcs_
.geturlnotify
= &NPN_GetURLNotify
;
126 host_funcs_
.posturlnotify
= &NPN_PostURLNotify
;
127 host_funcs_
.getvalue
= &NPN_GetValue
;
128 host_funcs_
.setvalue
= &NPN_SetValue
;
129 host_funcs_
.invalidaterect
= &NPN_InvalidateRect
;
130 host_funcs_
.invalidateregion
= &NPN_InvalidateRegion
;
131 host_funcs_
.forceredraw
= &NPN_ForceRedraw
;
133 // These come from the Javascript Engine
134 host_funcs_
.getstringidentifier
= WebBindings::getStringIdentifier
;
135 host_funcs_
.getstringidentifiers
= WebBindings::getStringIdentifiers
;
136 host_funcs_
.getintidentifier
= WebBindings::getIntIdentifier
;
137 host_funcs_
.identifierisstring
= WebBindings::identifierIsString
;
138 host_funcs_
.utf8fromidentifier
= WebBindings::utf8FromIdentifier
;
139 host_funcs_
.intfromidentifier
= WebBindings::intFromIdentifier
;
140 host_funcs_
.createobject
= WebBindings::createObject
;
141 host_funcs_
.retainobject
= WebBindings::retainObject
;
142 host_funcs_
.releaseobject
= WebBindings::releaseObject
;
143 host_funcs_
.invoke
= WebBindings::invoke
;
144 host_funcs_
.invokeDefault
= WebBindings::invokeDefault
;
145 host_funcs_
.evaluate
= WebBindings::evaluate
;
146 host_funcs_
.getproperty
= WebBindings::getProperty
;
147 host_funcs_
.setproperty
= WebBindings::setProperty
;
148 host_funcs_
.removeproperty
= WebBindings::removeProperty
;
149 host_funcs_
.hasproperty
= WebBindings::hasProperty
;
150 host_funcs_
.hasmethod
= WebBindings::hasMethod
;
151 host_funcs_
.releasevariantvalue
= WebBindings::releaseVariantValue
;
152 host_funcs_
.setexception
= WebBindings::setException
;
153 host_funcs_
.pushpopupsenabledstate
= NPN_PushPopupsEnabledState
;
154 host_funcs_
.poppopupsenabledstate
= NPN_PopPopupsEnabledState
;
155 host_funcs_
.enumerate
= WebBindings::enumerate
;
156 host_funcs_
.pluginthreadasynccall
= NPN_PluginThreadAsyncCall
;
157 host_funcs_
.construct
= WebBindings::construct
;
158 host_funcs_
.getvalueforurl
= NPN_GetValueForURL
;
159 host_funcs_
.setvalueforurl
= NPN_SetValueForURL
;
160 host_funcs_
.getauthenticationinfo
= NPN_GetAuthenticationInfo
;
161 host_funcs_
.scheduletimer
= NPN_ScheduleTimer
;
162 host_funcs_
.unscheduletimer
= NPN_UnscheduleTimer
;
163 host_funcs_
.popupcontextmenu
= NPN_PopUpContextMenu
;
164 host_funcs_
.convertpoint
= NPN_ConvertPoint
;
165 host_funcs_
.handleevent
= NPN_HandleEvent
;
166 host_funcs_
.unfocusinstance
= NPN_UnfocusInstance
;
167 host_funcs_
.urlredirectresponse
= NPN_URLRedirectResponse
;
170 void PluginHost::PatchNPNetscapeFuncs(NPNetscapeFuncs
* overrides
) {
171 // When running in the plugin process, we need to patch the NPN functions
172 // that the plugin calls to interact with NPObjects that we give. Otherwise
173 // the plugin will call the v8 NPN functions, which won't work since we have
174 // an NPObjectProxy and not a real v8 implementation.
175 if (overrides
->invoke
)
176 host_funcs_
.invoke
= overrides
->invoke
;
178 if (overrides
->invokeDefault
)
179 host_funcs_
.invokeDefault
= overrides
->invokeDefault
;
181 if (overrides
->evaluate
)
182 host_funcs_
.evaluate
= overrides
->evaluate
;
184 if (overrides
->getproperty
)
185 host_funcs_
.getproperty
= overrides
->getproperty
;
187 if (overrides
->setproperty
)
188 host_funcs_
.setproperty
= overrides
->setproperty
;
190 if (overrides
->removeproperty
)
191 host_funcs_
.removeproperty
= overrides
->removeproperty
;
193 if (overrides
->hasproperty
)
194 host_funcs_
.hasproperty
= overrides
->hasproperty
;
196 if (overrides
->hasmethod
)
197 host_funcs_
.hasmethod
= overrides
->hasmethod
;
199 if (overrides
->setexception
)
200 host_funcs_
.setexception
= overrides
->setexception
;
202 if (overrides
->enumerate
)
203 host_funcs_
.enumerate
= overrides
->enumerate
;
206 bool PluginHost::SetPostData(const char* buf
,
208 std::vector
<std::string
>* names
,
209 std::vector
<std::string
>* values
,
210 std::vector
<char>* body
) {
211 // Use a state table to do the parsing. Whitespace must be
212 // trimmed after the fact if desired. In our case, we actually
213 // don't care about the whitespace, because we're just going to
214 // pass this back into another POST. This function strips out the
215 // "Content-length" header and does not append it to the request.
218 // This parser takes action only on state changes.
222 // 0 GetHeader 1 2 4 0
223 // 1 GetValue 1 0 3 1
228 enum { INPUT_COLON
=0, INPUT_NEWLINE
, INPUT_NULL
, INPUT_OTHER
};
229 enum { GETNAME
, GETVALUE
, GETDATA
, DONE
, ERR
};
230 int statemachine
[3][4] = { { GETVALUE
, GETDATA
, GETDATA
, GETNAME
},
231 { GETVALUE
, GETNAME
, DONE
, GETVALUE
},
232 { GETDATA
, GETDATA
, DONE
, GETDATA
} };
233 std::string name
, value
;
234 const char* ptr
= static_cast<const char*>(buf
);
235 const char* start
= ptr
;
236 int state
= GETNAME
; // initial state
242 // Translate the current character into an input
243 // for the state table.
249 input
= INPUT_NEWLINE
;
259 int newstate
= statemachine
[state
][input
];
261 // Take action based on the new state.
262 if (state
!= newstate
) {
266 value
= std::string(start
, ptr
- start
);
267 base::TrimWhitespace(value
, base::TRIM_ALL
, &value
);
268 // If the name field is empty, we'll skip this header
269 // but we won't error out.
270 if (!name
.empty() && name
!= "content-length") {
271 names
->push_back(name
);
272 values
->push_back(value
);
278 name
= base::StringToLowerASCII(std::string(start
, ptr
- start
));
279 base::TrimWhitespace(name
, base::TRIM_ALL
, &name
);
283 // Finished headers, now get body
286 size_t previous_size
= body
->size();
287 size_t new_body_size
= length
- static_cast<int>(start
- buf
);
288 body
->resize(previous_size
+ new_body_size
);
290 memcpy(&body
->front() + previous_size
, start
, new_body_size
);
308 } // namespace content
312 using content::FindInstance
;
313 using content::PluginHost
;
314 using content::PluginInstance
;
315 using content::WebPlugin
;
317 // Allocates memory from the host's memory space.
318 void* NPN_MemAlloc(uint32_t size
) {
319 // Note: We must use the same allocator/deallocator
320 // that is used by the javascript library, as some of the
321 // JS APIs will pass memory to the plugin which the plugin
322 // will attempt to free.
326 // Deallocates memory from the host's memory space
327 void NPN_MemFree(void* ptr
) {
328 if (ptr
!= NULL
&& ptr
!= reinterpret_cast<void*>(-1))
332 // Requests that the host free a specified amount of memory.
333 uint32_t NPN_MemFlush(uint32_t size
) {
334 // This is not relevant on Windows; MAC specific
338 // This is for dynamic discovery of new plugins.
339 // Should force a re-scan of the plugins directory to load new ones.
340 void NPN_ReloadPlugins(NPBool reload_pages
) {
341 blink::resetPluginCache(reload_pages
? true : false);
344 // Requests a range of bytes for a seekable stream.
345 NPError
NPN_RequestRead(NPStream
* stream
, NPByteRange
* range_list
) {
346 if (!stream
|| !range_list
)
347 return NPERR_GENERIC_ERROR
;
349 scoped_refptr
<PluginInstance
> plugin(
350 reinterpret_cast<PluginInstance
*>(stream
->ndata
));
352 return NPERR_GENERIC_ERROR
;
354 plugin
->RequestRead(stream
, range_list
);
355 return NPERR_NO_ERROR
;
358 // Generic form of GetURL for common code between GetURL and GetURLNotify.
359 static NPError
GetURLNotify(NPP id
,
365 return NPERR_INVALID_URL
;
367 scoped_refptr
<PluginInstance
> plugin(FindInstance(id
));
369 return NPERR_GENERIC_ERROR
;
372 plugin
->RequestURL(url
, "GET", target
, NULL
, 0, notify
, notify_data
);
373 return NPERR_NO_ERROR
;
376 // Requests creation of a new stream with the contents of the
377 // specified URL; gets notification of the result.
378 NPError
NPN_GetURLNotify(NPP id
,
382 // This is identical to NPN_GetURL, but after finishing, the
383 // browser will call NPP_URLNotify to inform the plugin that
386 // According to the NPAPI documentation, if target == _self
387 // or a parent to _self, the browser should return NPERR_INVALID_PARAM,
388 // because it can't notify the plugin once deleted. This is
389 // absolutely false; firefox doesn't do this, and Flash relies on
390 // being able to use this.
392 // Also according to the NPAPI documentation, we should return
393 // NPERR_INVALID_URL if the url requested is not valid. However,
394 // this would require that we synchronously start fetching the
395 // URL. That just isn't practical. As such, there really is
396 // no way to return this error. From looking at the Firefox
397 // implementation, it doesn't look like Firefox does this either.
399 return GetURLNotify(id
, url
, target
, true, notify_data
);
402 NPError
NPN_GetURL(NPP id
, const char* url
, const char* target
) {
404 // Request from the Plugin to fetch content either for the plugin
405 // or to be placed into a browser window.
407 // If target == null, the browser fetches content and streams to plugin.
408 // otherwise, the browser loads content into an existing browser frame.
409 // If the target is the window/frame containing the plugin, the plugin
411 // If the target is _blank, a mailto: or news: url open content in a new
413 // If the target is _self, no other instance of the plugin is created. The
414 // plugin continues to operate in its own window
416 return GetURLNotify(id
, url
, target
, false, 0);
419 // Generic form of PostURL for common code between PostURL and PostURLNotify.
420 static NPError
PostURLNotify(NPP id
,
429 return NPERR_INVALID_URL
;
431 scoped_refptr
<PluginInstance
> plugin(FindInstance(id
));
434 return NPERR_GENERIC_ERROR
;
437 std::string post_file_contents
;
440 // Post data to be uploaded from a file. This can be handled in two
442 // 1. Read entire file and send the contents as if it was a post data
443 // specified in the argument
444 // 2. Send just the file details and read them in the browser at the
445 // time of sending the request.
446 // Approach 2 is more efficient but complicated. Approach 1 has a major
447 // drawback of sending potentially large data over two IPC hops. In a way
448 // 'large data over IPC' problem exists as it is in case of plugin giving
449 // the data directly instead of in a file.
450 // Currently we are going with the approach 1 to get the feature working.
451 // We can optimize this later with approach 2.
453 // TODO(joshia): Design a scheme to send a file descriptor instead of
454 // entire file contents across.
458 // Here we are blindly uploading whatever file requested by a plugin.
459 // This is risky as someone could exploit a plugin to send private
460 // data in arbitrary locations.
461 // A malicious (non-sandboxed) plugin has unfeterred access to OS
462 // resources and can do this anyway without using browser's HTTP stack.
463 // FWIW, Firefox and Safari don't perform any security checks.
466 return NPERR_FILE_NOT_FOUND
;
468 std::string
file_path_ascii(buf
);
469 base::FilePath file_path
;
470 static const char kFileUrlPrefix
[] = "file:";
471 if (StartsWithASCII(file_path_ascii
, kFileUrlPrefix
, false)) {
472 GURL
file_url(file_path_ascii
);
473 DCHECK(file_url
.SchemeIsFile());
474 net::FileURLToFilePath(file_url
, &file_path
);
476 file_path
= base::FilePath::FromUTF8Unsafe(file_path_ascii
);
479 base::File::Info post_file_info
;
480 if (!base::GetFileInfo(file_path
, &post_file_info
) ||
481 post_file_info
.is_directory
)
482 return NPERR_FILE_NOT_FOUND
;
484 if (!base::ReadFileToString(file_path
, &post_file_contents
))
485 return NPERR_FILE_NOT_FOUND
;
487 buf
= post_file_contents
.c_str();
488 len
= post_file_contents
.size();
491 // The post data sent by a plugin contains both headers
492 // and post data. Example:
493 // Content-type: text/html
494 // Content-length: 200
496 // <200 bytes of content here>
498 // Unfortunately, our stream needs these broken apart,
499 // so we need to parse the data and set headers and data
501 plugin
->RequestURL(url
, "POST", target
, buf
, len
, notify
, notify_data
);
502 return NPERR_NO_ERROR
;
505 NPError
NPN_PostURLNotify(NPP id
,
512 return PostURLNotify(id
, url
, target
, len
, buf
, file
, true, notify_data
);
515 NPError
NPN_PostURL(NPP id
,
521 // POSTs data to an URL, either from a temp file or a buffer.
522 // If file is true, buf contains a temp file (which host will delete after
523 // completing), and len contains the length of the filename.
524 // If file is false, buf contains the data to send, and len contains the
525 // length of the buffer
527 // If target is null,
528 // server response is returned to the plugin
529 // If target is _current, _self, or _top,
530 // server response is written to the plugin window and plugin is unloaded.
531 // If target is _new or _blank,
532 // server response is written to a new browser window
533 // If target is an existing frame,
534 // server response goes to that frame.
536 // For protocols other than FTP
537 // file uploads must be line-end converted from \r\n to \n
539 // Note: you cannot specify headers (even a blank line) in a memory buffer,
540 // use NPN_PostURLNotify
542 return PostURLNotify(id
, url
, target
, len
, buf
, file
, false, 0);
545 NPError
NPN_NewStream(NPP id
,
549 // Requests creation of a new data stream produced by the plugin,
550 // consumed by the browser.
552 // Browser should put this stream into a window target.
554 // TODO: implement me
555 DVLOG(1) << "NPN_NewStream is not implemented yet.";
556 return NPERR_GENERIC_ERROR
;
559 int32_t NPN_Write(NPP id
, NPStream
* stream
, int32_t len
, void* buffer
) {
560 // Writes data to an existing Plugin-created stream.
562 // TODO: implement me
563 DVLOG(1) << "NPN_Write is not implemented yet.";
564 return NPERR_GENERIC_ERROR
;
567 NPError
NPN_DestroyStream(NPP id
, NPStream
* stream
, NPReason reason
) {
568 // Destroys a stream (could be created by plugin or browser).
571 // NPRES_DONE - normal completion
572 // NPRES_USER_BREAK - user terminated
573 // NPRES_NETWORK_ERROR - network error (all errors fit here?)
577 scoped_refptr
<PluginInstance
> plugin(FindInstance(id
));
578 if (plugin
.get() == NULL
) {
580 return NPERR_GENERIC_ERROR
;
583 return plugin
->NPP_DestroyStream(stream
, reason
);
586 const char* NPN_UserAgent(NPP id
) {
588 // Flash passes in a null id during the NP_initialize call. We need to
589 // default to the Mozilla user agent if we don't have an NPP instance or
590 // else Flash won't request windowless mode.
591 bool use_mozilla_user_agent
= true;
593 scoped_refptr
<PluginInstance
> plugin
= FindInstance(id
);
594 if (plugin
.get() && !plugin
->use_mozilla_user_agent())
595 use_mozilla_user_agent
= false;
598 if (use_mozilla_user_agent
)
599 return "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9a1) "
600 "Gecko/20061103 Firefox/2.0a1";
603 // Provide a consistent user-agent string with memory that lasts
604 // long enough for the caller to read it.
605 static base::LazyInstance
<std::string
>::Leaky leaky_user_agent
=
606 LAZY_INSTANCE_INITIALIZER
;
607 if (leaky_user_agent
== NULL
)
608 leaky_user_agent
.Get() = content::GetContentClient()->GetUserAgent();
609 return leaky_user_agent
.Get().c_str();
612 void NPN_Status(NPP id
, const char* message
) {
613 // Displays a message on the status line of the browser window.
615 // TODO: implement me
616 DVLOG(1) << "NPN_Status is not implemented yet.";
619 void NPN_InvalidateRect(NPP id
, NPRect
*invalidRect
) {
620 // Invalidates specified drawing area prior to repainting or refreshing a
623 // Before a windowless plugin can refresh part of its drawing area, it must
624 // first invalidate it. This function causes the NPP_HandleEvent method to
625 // pass an update event or a paint message to the plug-in. After calling
626 // this method, the plug-in receives a paint message asynchronously.
628 // The browser redraws invalid areas of the document and any windowless
629 // plug-ins at regularly timed intervals. To force a paint message, the
630 // plug-in can call NPN_ForceRedraw after calling this method.
632 scoped_refptr
<PluginInstance
> plugin(FindInstance(id
));
633 if (plugin
.get() && plugin
->webplugin()) {
636 if (!plugin
->windowless()) {
638 rect
.left
= invalidRect
->left
;
639 rect
.right
= invalidRect
->right
;
640 rect
.top
= invalidRect
->top
;
641 rect
.bottom
= invalidRect
->bottom
;
642 ::InvalidateRect(plugin
->window_handle(), &rect
, false);
646 gfx::Rect
rect(invalidRect
->left
,
648 invalidRect
->right
- invalidRect
->left
,
649 invalidRect
->bottom
- invalidRect
->top
);
650 plugin
->webplugin()->InvalidateRect(rect
);
652 plugin
->webplugin()->Invalidate();
657 void NPN_InvalidateRegion(NPP id
, NPRegion invalidRegion
) {
658 // Invalidates a specified drawing region prior to repainting
659 // or refreshing a window-less plugin.
661 // Similar to NPN_InvalidateRect.
663 // TODO: this is overkill--add platform-specific region handling (at the
664 // very least, fetch the region's bounding box and pass it to InvalidateRect).
665 scoped_refptr
<PluginInstance
> plugin(FindInstance(id
));
666 DCHECK(plugin
.get() != NULL
);
667 if (plugin
.get() && plugin
->webplugin())
668 plugin
->webplugin()->Invalidate();
671 void NPN_ForceRedraw(NPP id
) {
672 // Forces repaint for a windowless plug-in.
674 // We deliberately do not implement this; we don't want plugins forcing
675 // synchronous paints.
678 NPError
NPN_GetValue(NPP id
, NPNVariable variable
, void* value
) {
679 // Allows the plugin to query the browser for information
682 // NPNVxDisplay (unix only)
683 // NPNVxtAppContext (unix only)
684 // NPNVnetscapeWindow (win only) - Gets the native window on which the
685 // plug-in drawing occurs, returns HWND
686 // NPNVjavascriptEnabledBool: tells whether Javascript is enabled
687 // NPNVasdEnabledBool: tells whether SmartUpdate is enabled
688 // NPNVOfflineBool: tells whether offline-mode is enabled
690 NPError rv
= NPERR_GENERIC_ERROR
;
692 switch (static_cast<int>(variable
)) {
693 case NPNVWindowNPObject
: {
694 scoped_refptr
<PluginInstance
> plugin(FindInstance(id
));
697 return NPERR_INVALID_INSTANCE_ERROR
;
699 NPObject
*np_object
= plugin
->webplugin()->GetWindowScriptNPObject();
700 // Return value is expected to be retained, as
702 // <http://www.mozilla.org/projects/plugins/npruntime.html#browseraccess>
704 WebBindings::retainObject(np_object
);
705 void **v
= (void **)value
;
713 case NPNVPluginElementNPObject
: {
714 scoped_refptr
<PluginInstance
> plugin(FindInstance(id
));
717 return NPERR_INVALID_INSTANCE_ERROR
;
719 NPObject
*np_object
= plugin
->webplugin()->GetPluginElement();
720 // Return value is expected to be retained, as
722 // <http://www.mozilla.org/projects/plugins/npruntime.html#browseraccess>
724 WebBindings::retainObject(np_object
);
725 void** v
= static_cast<void**>(value
);
733 #if !defined(OS_MACOSX) // OS X doesn't have windowed plugins.
734 case NPNVnetscapeWindow
: {
735 scoped_refptr
<PluginInstance
> plugin
= FindInstance(id
);
738 return NPERR_INVALID_INSTANCE_ERROR
;
740 gfx::PluginWindowHandle handle
= plugin
->window_handle();
741 *((void**)value
) = (void*)handle
;
746 case NPNVjavascriptEnabledBool
: {
747 // yes, JS is enabled.
748 *((void**)value
) = (void*)1;
752 case NPNVSupportsWindowless
: {
753 NPBool
* supports_windowless
= reinterpret_cast<NPBool
*>(value
);
754 *supports_windowless
= true;
758 case NPNVprivateModeBool
: {
759 NPBool
* private_mode
= reinterpret_cast<NPBool
*>(value
);
760 scoped_refptr
<PluginInstance
> plugin(FindInstance(id
));
763 return NPERR_INVALID_INSTANCE_ERROR
;
765 *private_mode
= plugin
->webplugin()->IsOffTheRecord();
769 #if defined(OS_MACOSX)
770 case NPNVpluginDrawingModel
: {
771 // return the drawing model that was negotiated when we initialized.
772 scoped_refptr
<PluginInstance
> plugin(FindInstance(id
));
775 return NPERR_INVALID_INSTANCE_ERROR
;
777 *reinterpret_cast<int*>(value
) = plugin
->drawing_model();
781 case NPNVsupportsCoreGraphicsBool
:
782 case NPNVsupportsCocoaBool
: {
783 // These drawing and event models are always supported.
784 NPBool
* supports_model
= reinterpret_cast<NPBool
*>(value
);
785 *supports_model
= true;
789 case NPNVsupportsInvalidatingCoreAnimationBool
:
790 case NPNVsupportsCoreAnimationBool
: {
791 NPBool
* supports_model
= reinterpret_cast<NPBool
*>(value
);
792 *supports_model
= content::SupportsCoreAnimationPlugins();
797 case NPNVsupportsCarbonBool
:
799 #ifndef NP_NO_QUICKDRAW
800 case NPNVsupportsQuickDrawBool
:
802 case NPNVsupportsOpenGLBool
: {
803 // These models are never supported. OpenGL was never widely supported,
804 // and QuickDraw and Carbon have been deprecated for quite some time.
805 NPBool
* supports_model
= reinterpret_cast<NPBool
*>(value
);
806 *supports_model
= false;
810 case NPNVsupportsCompositingCoreAnimationPluginsBool
: {
811 NPBool
* supports_compositing
= reinterpret_cast<NPBool
*>(value
);
812 *supports_compositing
= content::SupportsCoreAnimationPlugins();
816 case NPNVsupportsUpdatedCocoaTextInputBool
: {
817 // We support the clarifications to the Cocoa IME event spec.
818 NPBool
* supports_update
= reinterpret_cast<NPBool
*>(value
);
819 *supports_update
= true;
825 DVLOG(1) << "NPN_GetValue(" << variable
<< ") is not implemented yet.";
831 NPError
NPN_SetValue(NPP id
, NPPVariable variable
, void* value
) {
832 // Allows the plugin to set various modes
834 scoped_refptr
<PluginInstance
> plugin(FindInstance(id
));
837 return NPERR_INVALID_INSTANCE_ERROR
;
840 case NPPVpluginWindowBool
: {
841 // Sets windowless mode for display of the plugin
842 // Note: the documentation at
843 // http://developer.mozilla.org/en/docs/NPN_SetValue is wrong. When
844 // value is NULL, the mode is set to true. This is the same way Mozilla
846 plugin
->set_windowless(value
== 0);
847 return NPERR_NO_ERROR
;
849 case NPPVpluginTransparentBool
: {
850 // Sets transparent mode for display of the plugin
852 // Transparent plugins require the browser to paint the background
853 // before having the plugin paint. By default, windowless plugins
854 // are transparent. Making a windowless plugin opaque means that
855 // the plugin does not require the browser to paint the background.
856 bool mode
= (value
!= 0);
857 plugin
->set_transparent(mode
);
858 return NPERR_NO_ERROR
;
860 case NPPVjavascriptPushCallerBool
:
861 // Specifies whether you are pushing or popping the JSContext off.
863 // TODO: implement me
864 DVLOG(1) << "NPN_SetValue(NPPVJavascriptPushCallerBool) is not "
866 return NPERR_GENERIC_ERROR
;
867 case NPPVpluginKeepLibraryInMemory
:
868 // Tells browser that plugin library should live longer than usual.
869 // TODO: implement me
870 DVLOG(1) << "NPN_SetValue(NPPVpluginKeepLibraryInMemory) is not "
872 return NPERR_GENERIC_ERROR
;
873 #if defined(OS_MACOSX)
874 case NPPVpluginDrawingModel
: {
875 intptr_t model
= reinterpret_cast<intptr_t>(value
);
876 if (model
== NPDrawingModelCoreGraphics
||
877 ((model
== NPDrawingModelInvalidatingCoreAnimation
||
878 model
== NPDrawingModelCoreAnimation
) &&
879 content::SupportsCoreAnimationPlugins())) {
880 plugin
->set_drawing_model(static_cast<NPDrawingModel
>(model
));
881 return NPERR_NO_ERROR
;
883 return NPERR_GENERIC_ERROR
;
885 case NPPVpluginEventModel
: {
886 // Only the Cocoa event model is supported.
887 intptr_t model
= reinterpret_cast<intptr_t>(value
);
888 if (model
== NPEventModelCocoa
) {
889 plugin
->set_event_model(static_cast<NPEventModel
>(model
));
890 return NPERR_NO_ERROR
;
892 return NPERR_GENERIC_ERROR
;
896 // TODO: implement me
897 DVLOG(1) << "NPN_SetValue(" << variable
<< ") is not implemented.";
902 return NPERR_GENERIC_ERROR
;
905 void* NPN_GetJavaEnv() {
906 // TODO: implement me
907 DVLOG(1) << "NPN_GetJavaEnv is not implemented.";
911 void* NPN_GetJavaPeer(NPP
) {
912 // TODO: implement me
913 DVLOG(1) << "NPN_GetJavaPeer is not implemented.";
917 void NPN_PushPopupsEnabledState(NPP id
, NPBool enabled
) {
918 scoped_refptr
<PluginInstance
> plugin(FindInstance(id
));
920 plugin
->PushPopupsEnabledState(enabled
? true : false);
923 void NPN_PopPopupsEnabledState(NPP id
) {
924 scoped_refptr
<PluginInstance
> plugin(FindInstance(id
));
926 plugin
->PopPopupsEnabledState();
929 void NPN_PluginThreadAsyncCall(NPP id
,
932 scoped_refptr
<PluginInstance
> plugin(FindInstance(id
));
934 plugin
->PluginThreadAsyncCall(func
, user_data
);
937 NPError
NPN_GetValueForURL(NPP id
,
938 NPNURLVariable variable
,
943 return NPERR_INVALID_PARAM
;
945 if (!url
|| !*url
|| !len
)
946 return NPERR_INVALID_URL
;
954 scoped_refptr
<PluginInstance
> plugin(FindInstance(id
));
956 return NPERR_GENERIC_ERROR
;
958 WebPlugin
* webplugin
= plugin
->webplugin();
960 return NPERR_GENERIC_ERROR
;
962 if (!webplugin
->FindProxyForUrl(GURL(std::string(url
)), &result
))
963 return NPERR_GENERIC_ERROR
;
966 case NPNURLVCookie
: {
967 scoped_refptr
<PluginInstance
> plugin(FindInstance(id
));
969 return NPERR_GENERIC_ERROR
;
971 WebPlugin
* webplugin
= plugin
->webplugin();
973 return NPERR_GENERIC_ERROR
;
975 // Bypass third-party cookie blocking by using the url as the
976 // first_party_for_cookies.
977 GURL
cookies_url((std::string(url
)));
978 result
= webplugin
->GetCookies(cookies_url
, cookies_url
);
982 return NPERR_GENERIC_ERROR
;
985 // Allocate this using the NPAPI allocator. The plugin will call
986 // NPN_Free to free this.
987 *value
= static_cast<char*>(NPN_MemAlloc(result
.length() + 1));
988 base::strlcpy(*value
, result
.c_str(), result
.length() + 1);
989 *len
= result
.length();
991 return NPERR_NO_ERROR
;
994 NPError
NPN_SetValueForURL(NPP id
,
995 NPNURLVariable variable
,
1000 return NPERR_INVALID_PARAM
;
1003 return NPERR_INVALID_URL
;
1006 case NPNURLVCookie
: {
1007 scoped_refptr
<PluginInstance
> plugin(FindInstance(id
));
1009 return NPERR_GENERIC_ERROR
;
1011 WebPlugin
* webplugin
= plugin
->webplugin();
1013 return NPERR_GENERIC_ERROR
;
1015 std::string
cookie(value
, len
);
1016 GURL
cookies_url((std::string(url
)));
1017 webplugin
->SetCookie(cookies_url
, cookies_url
, cookie
);
1018 return NPERR_NO_ERROR
;
1021 // We don't support setting proxy values, fall through...
1024 // Fall through and return an error...
1028 return NPERR_GENERIC_ERROR
;
1031 NPError
NPN_GetAuthenticationInfo(NPP id
,
1032 const char* protocol
,
1041 if (!id
|| !protocol
|| !host
|| !scheme
|| !realm
|| !username
||
1042 !ulen
|| !password
|| !plen
)
1043 return NPERR_INVALID_PARAM
;
1045 // TODO: implement me (bug 23928)
1046 return NPERR_GENERIC_ERROR
;
1049 uint32_t NPN_ScheduleTimer(NPP id
,
1052 void (*func
)(NPP id
, uint32_t timer_id
)) {
1053 scoped_refptr
<PluginInstance
> plugin(FindInstance(id
));
1057 return plugin
->ScheduleTimer(interval
, repeat
, func
);
1060 void NPN_UnscheduleTimer(NPP id
, uint32_t timer_id
) {
1061 scoped_refptr
<PluginInstance
> plugin(FindInstance(id
));
1063 plugin
->UnscheduleTimer(timer_id
);
1066 NPError
NPN_PopUpContextMenu(NPP id
, NPMenu
* menu
) {
1068 return NPERR_INVALID_PARAM
;
1070 scoped_refptr
<PluginInstance
> plugin(FindInstance(id
));
1072 return plugin
->PopUpContextMenu(menu
);
1075 return NPERR_GENERIC_ERROR
;
1078 NPBool
NPN_ConvertPoint(NPP id
, double sourceX
, double sourceY
,
1079 NPCoordinateSpace sourceSpace
,
1080 double *destX
, double *destY
,
1081 NPCoordinateSpace destSpace
) {
1082 scoped_refptr
<PluginInstance
> plugin(FindInstance(id
));
1084 return plugin
->ConvertPoint(
1085 sourceX
, sourceY
, sourceSpace
, destX
, destY
, destSpace
);
1091 NPBool
NPN_HandleEvent(NPP id
, void *event
, NPBool handled
) {
1092 // TODO: Implement advanced key handling: http://crbug.com/46578
1097 NPBool
NPN_UnfocusInstance(NPP id
, NPFocusDirection direction
) {
1098 // TODO: Implement advanced key handling: http://crbug.com/46578
1103 void NPN_URLRedirectResponse(NPP instance
, void* notify_data
, NPBool allow
) {
1104 scoped_refptr
<PluginInstance
> plugin(FindInstance(instance
));
1106 plugin
->URLRedirectResponse(!!allow
, notify_data
);