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/logging.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/strings/string_piece.h"
12 #include "base/strings/string_util.h"
13 #include "base/strings/sys_string_conversions.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "build/build_config.h"
16 #include "content/child/npapi/plugin_instance.h"
17 #include "content/child/npapi/plugin_lib.h"
18 #include "content/child/npapi/plugin_stream_url.h"
19 #include "content/child/npapi/webplugin_delegate.h"
20 #include "content/public/common/content_client.h"
21 #include "content/public/common/content_switches.h"
22 #include "content/public/common/user_agent.h"
23 #include "content/public/common/webplugininfo.h"
24 #include "net/base/net_util.h"
25 #include "third_party/WebKit/public/web/WebBindings.h"
26 #include "third_party/WebKit/public/web/WebKit.h"
27 #include "third_party/npapi/bindings/npruntime.h"
28 #include "ui/gl/gl_implementation.h"
29 #include "ui/gl/gl_surface.h"
31 #if defined(OS_MACOSX)
32 #include "base/mac/mac_util.h"
35 using blink::WebBindings;
37 // Declarations for stub implementations of deprecated functions, which are no
38 // longer listed in npapi.h.
40 void* NPN_GetJavaEnv();
41 void* NPN_GetJavaPeer(NPP);
46 // Finds a PluginInstance from an NPP.
47 // The caller must take a reference if needed.
48 static PluginInstance* FindInstance(NPP id) {
52 return reinterpret_cast<PluginInstance*>(id->ndata);
55 #if defined(OS_MACOSX)
56 // Returns true if Core Animation plugins are supported. This requires that the
57 // OS supports shared accelerated surfaces via IOSurface. This is true on Snow
58 // Leopard and higher.
59 static bool SupportsCoreAnimationPlugins() {
60 if (CommandLine::ForCurrentProcess()->HasSwitch(
61 switches::kDisableCoreAnimationPlugins))
63 // We also need to be running with desktop GL and not the software
64 // OSMesa renderer in order to share accelerated surfaces between
65 // processes. Because on MacOS we lazy-initialize GLSurface in the
66 // renderer process here, ensure we're not also initializing GL somewhere
67 // else, and that we only do this once.
68 static gfx::GLImplementation implementation = gfx::kGLImplementationNone;
69 if (implementation == gfx::kGLImplementationNone) {
70 // Not initialized yet.
71 DCHECK_EQ(implementation, gfx::GetGLImplementation())
72 << "GL already initialized by someone else to: "
73 << gfx::GetGLImplementation();
74 if (!gfx::GLSurface::InitializeOneOff()) {
77 implementation = gfx::GetGLImplementation();
79 return (implementation == gfx::kGLImplementationDesktopGL);
83 PluginHost::PluginHost() {
84 InitializeHostFuncs();
87 PluginHost::~PluginHost() {
90 PluginHost *PluginHost::Singleton() {
91 CR_DEFINE_STATIC_LOCAL(scoped_refptr<PluginHost>, singleton, ());
92 if (singleton.get() == NULL) {
93 singleton = new PluginHost();
96 DCHECK(singleton.get() != NULL);
97 return singleton.get();
100 void PluginHost::InitializeHostFuncs() {
101 memset(&host_funcs_, 0, sizeof(host_funcs_));
102 host_funcs_.size = sizeof(host_funcs_);
103 host_funcs_.version = (NP_VERSION_MAJOR << 8) | (NP_VERSION_MINOR);
105 // The "basic" functions
106 host_funcs_.geturl = &NPN_GetURL;
107 host_funcs_.posturl = &NPN_PostURL;
108 host_funcs_.requestread = &NPN_RequestRead;
109 host_funcs_.newstream = &NPN_NewStream;
110 host_funcs_.write = &NPN_Write;
111 host_funcs_.destroystream = &NPN_DestroyStream;
112 host_funcs_.status = &NPN_Status;
113 host_funcs_.uagent = &NPN_UserAgent;
114 host_funcs_.memalloc = &NPN_MemAlloc;
115 host_funcs_.memfree = &NPN_MemFree;
116 host_funcs_.memflush = &NPN_MemFlush;
117 host_funcs_.reloadplugins = &NPN_ReloadPlugins;
119 // Stubs for deprecated Java functions
120 host_funcs_.getJavaEnv = &NPN_GetJavaEnv;
121 host_funcs_.getJavaPeer = &NPN_GetJavaPeer;
123 // Advanced functions we implement
124 host_funcs_.geturlnotify = &NPN_GetURLNotify;
125 host_funcs_.posturlnotify = &NPN_PostURLNotify;
126 host_funcs_.getvalue = &NPN_GetValue;
127 host_funcs_.setvalue = &NPN_SetValue;
128 host_funcs_.invalidaterect = &NPN_InvalidateRect;
129 host_funcs_.invalidateregion = &NPN_InvalidateRegion;
130 host_funcs_.forceredraw = &NPN_ForceRedraw;
132 // These come from the Javascript Engine
133 host_funcs_.getstringidentifier = WebBindings::getStringIdentifier;
134 host_funcs_.getstringidentifiers = WebBindings::getStringIdentifiers;
135 host_funcs_.getintidentifier = WebBindings::getIntIdentifier;
136 host_funcs_.identifierisstring = WebBindings::identifierIsString;
137 host_funcs_.utf8fromidentifier = WebBindings::utf8FromIdentifier;
138 host_funcs_.intfromidentifier = WebBindings::intFromIdentifier;
139 host_funcs_.createobject = WebBindings::createObject;
140 host_funcs_.retainobject = WebBindings::retainObject;
141 host_funcs_.releaseobject = WebBindings::releaseObject;
142 host_funcs_.invoke = WebBindings::invoke;
143 host_funcs_.invokeDefault = WebBindings::invokeDefault;
144 host_funcs_.evaluate = WebBindings::evaluate;
145 host_funcs_.getproperty = WebBindings::getProperty;
146 host_funcs_.setproperty = WebBindings::setProperty;
147 host_funcs_.removeproperty = WebBindings::removeProperty;
148 host_funcs_.hasproperty = WebBindings::hasProperty;
149 host_funcs_.hasmethod = WebBindings::hasMethod;
150 host_funcs_.releasevariantvalue = WebBindings::releaseVariantValue;
151 host_funcs_.setexception = WebBindings::setException;
152 host_funcs_.pushpopupsenabledstate = NPN_PushPopupsEnabledState;
153 host_funcs_.poppopupsenabledstate = NPN_PopPopupsEnabledState;
154 host_funcs_.enumerate = WebBindings::enumerate;
155 host_funcs_.pluginthreadasynccall = NPN_PluginThreadAsyncCall;
156 host_funcs_.construct = WebBindings::construct;
157 host_funcs_.getvalueforurl = NPN_GetValueForURL;
158 host_funcs_.setvalueforurl = NPN_SetValueForURL;
159 host_funcs_.getauthenticationinfo = NPN_GetAuthenticationInfo;
160 host_funcs_.scheduletimer = NPN_ScheduleTimer;
161 host_funcs_.unscheduletimer = NPN_UnscheduleTimer;
162 host_funcs_.popupcontextmenu = NPN_PopUpContextMenu;
163 host_funcs_.convertpoint = NPN_ConvertPoint;
164 host_funcs_.handleevent = NPN_HandleEvent;
165 host_funcs_.unfocusinstance = NPN_UnfocusInstance;
166 host_funcs_.urlredirectresponse = NPN_URLRedirectResponse;
169 void PluginHost::PatchNPNetscapeFuncs(NPNetscapeFuncs* overrides) {
170 // When running in the plugin process, we need to patch the NPN functions
171 // that the plugin calls to interact with NPObjects that we give. Otherwise
172 // the plugin will call the v8 NPN functions, which won't work since we have
173 // an NPObjectProxy and not a real v8 implementation.
174 if (overrides->invoke)
175 host_funcs_.invoke = overrides->invoke;
177 if (overrides->invokeDefault)
178 host_funcs_.invokeDefault = overrides->invokeDefault;
180 if (overrides->evaluate)
181 host_funcs_.evaluate = overrides->evaluate;
183 if (overrides->getproperty)
184 host_funcs_.getproperty = overrides->getproperty;
186 if (overrides->setproperty)
187 host_funcs_.setproperty = overrides->setproperty;
189 if (overrides->removeproperty)
190 host_funcs_.removeproperty = overrides->removeproperty;
192 if (overrides->hasproperty)
193 host_funcs_.hasproperty = overrides->hasproperty;
195 if (overrides->hasmethod)
196 host_funcs_.hasmethod = overrides->hasmethod;
198 if (overrides->setexception)
199 host_funcs_.setexception = overrides->setexception;
201 if (overrides->enumerate)
202 host_funcs_.enumerate = overrides->enumerate;
205 bool PluginHost::SetPostData(const char* buf,
207 std::vector<std::string>* names,
208 std::vector<std::string>* values,
209 std::vector<char>* body) {
210 // Use a state table to do the parsing. Whitespace must be
211 // trimmed after the fact if desired. In our case, we actually
212 // don't care about the whitespace, because we're just going to
213 // pass this back into another POST. This function strips out the
214 // "Content-length" header and does not append it to the request.
217 // This parser takes action only on state changes.
221 // 0 GetHeader 1 2 4 0
222 // 1 GetValue 1 0 3 1
227 enum { INPUT_COLON=0, INPUT_NEWLINE, INPUT_NULL, INPUT_OTHER };
228 enum { GETNAME, GETVALUE, GETDATA, DONE, ERR };
229 int statemachine[3][4] = { { GETVALUE, GETDATA, GETDATA, GETNAME },
230 { GETVALUE, GETNAME, DONE, GETVALUE },
231 { GETDATA, GETDATA, DONE, GETDATA } };
232 std::string name, value;
233 const char* ptr = static_cast<const char*>(buf);
234 const char* start = ptr;
235 int state = GETNAME; // initial state
241 // Translate the current character into an input
242 // for the state table.
248 input = INPUT_NEWLINE;
258 int newstate = statemachine[state][input];
260 // Take action based on the new state.
261 if (state != newstate) {
265 value = std::string(start, ptr - start);
266 base::TrimWhitespace(value, base::TRIM_ALL, &value);
267 // If the name field is empty, we'll skip this header
268 // but we won't error out.
269 if (!name.empty() && name != "content-length") {
270 names->push_back(name);
271 values->push_back(value);
277 name = StringToLowerASCII(std::string(start, ptr - start));
278 base::TrimWhitespace(name, base::TRIM_ALL, &name);
282 // Finished headers, now get body
285 size_t previous_size = body->size();
286 size_t new_body_size = length - static_cast<int>(start - buf);
287 body->resize(previous_size + new_body_size);
289 memcpy(&body->front() + previous_size, start, new_body_size);
307 } // namespace content
311 using content::FindInstance;
312 using content::PluginHost;
313 using content::PluginInstance;
314 using content::WebPlugin;
316 // Allocates memory from the host's memory space.
317 void* NPN_MemAlloc(uint32_t size) {
318 // Note: We must use the same allocator/deallocator
319 // that is used by the javascript library, as some of the
320 // JS APIs will pass memory to the plugin which the plugin
321 // will attempt to free.
325 // Deallocates memory from the host's memory space
326 void NPN_MemFree(void* ptr) {
327 if (ptr != NULL && ptr != reinterpret_cast<void*>(-1))
331 // Requests that the host free a specified amount of memory.
332 uint32_t NPN_MemFlush(uint32_t size) {
333 // This is not relevant on Windows; MAC specific
337 // This is for dynamic discovery of new plugins.
338 // Should force a re-scan of the plugins directory to load new ones.
339 void NPN_ReloadPlugins(NPBool reload_pages) {
340 blink::resetPluginCache(reload_pages ? true : false);
343 // Requests a range of bytes for a seekable stream.
344 NPError NPN_RequestRead(NPStream* stream, NPByteRange* range_list) {
345 if (!stream || !range_list)
346 return NPERR_GENERIC_ERROR;
348 scoped_refptr<PluginInstance> plugin(
349 reinterpret_cast<PluginInstance*>(stream->ndata));
351 return NPERR_GENERIC_ERROR;
353 plugin->RequestRead(stream, range_list);
354 return NPERR_NO_ERROR;
357 // Generic form of GetURL for common code between GetURL and GetURLNotify.
358 static NPError GetURLNotify(NPP id,
364 return NPERR_INVALID_URL;
366 scoped_refptr<PluginInstance> plugin(FindInstance(id));
368 return NPERR_GENERIC_ERROR;
371 plugin->RequestURL(url, "GET", target, NULL, 0, notify, notify_data);
372 return NPERR_NO_ERROR;
375 // Requests creation of a new stream with the contents of the
376 // specified URL; gets notification of the result.
377 NPError NPN_GetURLNotify(NPP id,
381 // This is identical to NPN_GetURL, but after finishing, the
382 // browser will call NPP_URLNotify to inform the plugin that
385 // According to the NPAPI documentation, if target == _self
386 // or a parent to _self, the browser should return NPERR_INVALID_PARAM,
387 // because it can't notify the plugin once deleted. This is
388 // absolutely false; firefox doesn't do this, and Flash relies on
389 // being able to use this.
391 // Also according to the NPAPI documentation, we should return
392 // NPERR_INVALID_URL if the url requested is not valid. However,
393 // this would require that we synchronously start fetching the
394 // URL. That just isn't practical. As such, there really is
395 // no way to return this error. From looking at the Firefox
396 // implementation, it doesn't look like Firefox does this either.
398 return GetURLNotify(id, url, target, true, notify_data);
401 NPError NPN_GetURL(NPP id, const char* url, const char* target) {
403 // Request from the Plugin to fetch content either for the plugin
404 // or to be placed into a browser window.
406 // If target == null, the browser fetches content and streams to plugin.
407 // otherwise, the browser loads content into an existing browser frame.
408 // If the target is the window/frame containing the plugin, the plugin
410 // If the target is _blank, a mailto: or news: url open content in a new
412 // If the target is _self, no other instance of the plugin is created. The
413 // plugin continues to operate in its own window
415 return GetURLNotify(id, url, target, false, 0);
418 // Generic form of PostURL for common code between PostURL and PostURLNotify.
419 static NPError PostURLNotify(NPP id,
428 return NPERR_INVALID_URL;
430 scoped_refptr<PluginInstance> plugin(FindInstance(id));
433 return NPERR_GENERIC_ERROR;
436 std::string post_file_contents;
439 // Post data to be uploaded from a file. This can be handled in two
441 // 1. Read entire file and send the contents as if it was a post data
442 // specified in the argument
443 // 2. Send just the file details and read them in the browser at the
444 // time of sending the request.
445 // Approach 2 is more efficient but complicated. Approach 1 has a major
446 // drawback of sending potentially large data over two IPC hops. In a way
447 // 'large data over IPC' problem exists as it is in case of plugin giving
448 // the data directly instead of in a file.
449 // Currently we are going with the approach 1 to get the feature working.
450 // We can optimize this later with approach 2.
452 // TODO(joshia): Design a scheme to send a file descriptor instead of
453 // entire file contents across.
457 // Here we are blindly uploading whatever file requested by a plugin.
458 // This is risky as someone could exploit a plugin to send private
459 // data in arbitrary locations.
460 // A malicious (non-sandboxed) plugin has unfeterred access to OS
461 // resources and can do this anyway without using browser's HTTP stack.
462 // FWIW, Firefox and Safari don't perform any security checks.
465 return NPERR_FILE_NOT_FOUND;
467 std::string file_path_ascii(buf);
468 base::FilePath file_path;
469 static const char kFileUrlPrefix[] = "file:";
470 if (StartsWithASCII(file_path_ascii, kFileUrlPrefix, false)) {
471 GURL file_url(file_path_ascii);
472 DCHECK(file_url.SchemeIsFile());
473 net::FileURLToFilePath(file_url, &file_path);
475 file_path = base::FilePath::FromUTF8Unsafe(file_path_ascii);
478 base::File::Info post_file_info;
479 if (!base::GetFileInfo(file_path, &post_file_info) ||
480 post_file_info.is_directory)
481 return NPERR_FILE_NOT_FOUND;
483 if (!base::ReadFileToString(file_path, &post_file_contents))
484 return NPERR_FILE_NOT_FOUND;
486 buf = post_file_contents.c_str();
487 len = post_file_contents.size();
490 // The post data sent by a plugin contains both headers
491 // and post data. Example:
492 // Content-type: text/html
493 // Content-length: 200
495 // <200 bytes of content here>
497 // Unfortunately, our stream needs these broken apart,
498 // so we need to parse the data and set headers and data
500 plugin->RequestURL(url, "POST", target, buf, len, notify, notify_data);
501 return NPERR_NO_ERROR;
504 NPError NPN_PostURLNotify(NPP id,
511 return PostURLNotify(id, url, target, len, buf, file, true, notify_data);
514 NPError NPN_PostURL(NPP id,
520 // POSTs data to an URL, either from a temp file or a buffer.
521 // If file is true, buf contains a temp file (which host will delete after
522 // completing), and len contains the length of the filename.
523 // If file is false, buf contains the data to send, and len contains the
524 // length of the buffer
526 // If target is null,
527 // server response is returned to the plugin
528 // If target is _current, _self, or _top,
529 // server response is written to the plugin window and plugin is unloaded.
530 // If target is _new or _blank,
531 // server response is written to a new browser window
532 // If target is an existing frame,
533 // server response goes to that frame.
535 // For protocols other than FTP
536 // file uploads must be line-end converted from \r\n to \n
538 // Note: you cannot specify headers (even a blank line) in a memory buffer,
539 // use NPN_PostURLNotify
541 return PostURLNotify(id, url, target, len, buf, file, false, 0);
544 NPError NPN_NewStream(NPP id,
548 // Requests creation of a new data stream produced by the plugin,
549 // consumed by the browser.
551 // Browser should put this stream into a window target.
553 // TODO: implement me
554 DVLOG(1) << "NPN_NewStream is not implemented yet.";
555 return NPERR_GENERIC_ERROR;
558 int32_t NPN_Write(NPP id, NPStream* stream, int32_t len, void* buffer) {
559 // Writes data to an existing Plugin-created stream.
561 // TODO: implement me
562 DVLOG(1) << "NPN_Write is not implemented yet.";
563 return NPERR_GENERIC_ERROR;
566 NPError NPN_DestroyStream(NPP id, NPStream* stream, NPReason reason) {
567 // Destroys a stream (could be created by plugin or browser).
570 // NPRES_DONE - normal completion
571 // NPRES_USER_BREAK - user terminated
572 // NPRES_NETWORK_ERROR - network error (all errors fit here?)
576 scoped_refptr<PluginInstance> plugin(FindInstance(id));
577 if (plugin.get() == NULL) {
579 return NPERR_GENERIC_ERROR;
582 return plugin->NPP_DestroyStream(stream, reason);
585 const char* NPN_UserAgent(NPP id) {
587 // Flash passes in a null id during the NP_initialize call. We need to
588 // default to the Mozilla user agent if we don't have an NPP instance or
589 // else Flash won't request windowless mode.
590 bool use_mozilla_user_agent = true;
592 scoped_refptr<PluginInstance> plugin = FindInstance(id);
593 if (plugin.get() && !plugin->use_mozilla_user_agent())
594 use_mozilla_user_agent = false;
597 if (use_mozilla_user_agent)
598 return "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9a1) "
599 "Gecko/20061103 Firefox/2.0a1";
602 return content::GetContentClient()->GetUserAgent().c_str();
605 void NPN_Status(NPP id, const char* message) {
606 // Displays a message on the status line of the browser window.
608 // TODO: implement me
609 DVLOG(1) << "NPN_Status is not implemented yet.";
612 void NPN_InvalidateRect(NPP id, NPRect *invalidRect) {
613 // Invalidates specified drawing area prior to repainting or refreshing a
616 // Before a windowless plugin can refresh part of its drawing area, it must
617 // first invalidate it. This function causes the NPP_HandleEvent method to
618 // pass an update event or a paint message to the plug-in. After calling
619 // this method, the plug-in recieves a paint message asynchronously.
621 // The browser redraws invalid areas of the document and any windowless
622 // plug-ins at regularly timed intervals. To force a paint message, the
623 // plug-in can call NPN_ForceRedraw after calling this method.
625 scoped_refptr<PluginInstance> plugin(FindInstance(id));
626 if (plugin.get() && plugin->webplugin()) {
629 if (!plugin->windowless()) {
631 rect.left = invalidRect->left;
632 rect.right = invalidRect->right;
633 rect.top = invalidRect->top;
634 rect.bottom = invalidRect->bottom;
635 ::InvalidateRect(plugin->window_handle(), &rect, false);
639 gfx::Rect rect(invalidRect->left,
641 invalidRect->right - invalidRect->left,
642 invalidRect->bottom - invalidRect->top);
643 plugin->webplugin()->InvalidateRect(rect);
645 plugin->webplugin()->Invalidate();
650 void NPN_InvalidateRegion(NPP id, NPRegion invalidRegion) {
651 // Invalidates a specified drawing region prior to repainting
652 // or refreshing a window-less plugin.
654 // Similar to NPN_InvalidateRect.
656 // TODO: this is overkill--add platform-specific region handling (at the
657 // very least, fetch the region's bounding box and pass it to InvalidateRect).
658 scoped_refptr<PluginInstance> plugin(FindInstance(id));
659 DCHECK(plugin.get() != NULL);
660 if (plugin.get() && plugin->webplugin())
661 plugin->webplugin()->Invalidate();
664 void NPN_ForceRedraw(NPP id) {
665 // Forces repaint for a windowless plug-in.
667 // We deliberately do not implement this; we don't want plugins forcing
668 // synchronous paints.
671 NPError NPN_GetValue(NPP id, NPNVariable variable, void* value) {
672 // Allows the plugin to query the browser for information
675 // NPNVxDisplay (unix only)
676 // NPNVxtAppContext (unix only)
677 // NPNVnetscapeWindow (win only) - Gets the native window on which the
678 // plug-in drawing occurs, returns HWND
679 // NPNVjavascriptEnabledBool: tells whether Javascript is enabled
680 // NPNVasdEnabledBool: tells whether SmartUpdate is enabled
681 // NPNVOfflineBool: tells whether offline-mode is enabled
683 NPError rv = NPERR_GENERIC_ERROR;
685 switch (static_cast<int>(variable)) {
686 case NPNVWindowNPObject: {
687 scoped_refptr<PluginInstance> plugin(FindInstance(id));
690 return NPERR_INVALID_INSTANCE_ERROR;
692 NPObject *np_object = plugin->webplugin()->GetWindowScriptNPObject();
693 // Return value is expected to be retained, as
695 // <http://www.mozilla.org/projects/plugins/npruntime.html#browseraccess>
697 WebBindings::retainObject(np_object);
698 void **v = (void **)value;
706 case NPNVPluginElementNPObject: {
707 scoped_refptr<PluginInstance> plugin(FindInstance(id));
710 return NPERR_INVALID_INSTANCE_ERROR;
712 NPObject *np_object = plugin->webplugin()->GetPluginElement();
713 // Return value is expected to be retained, as
715 // <http://www.mozilla.org/projects/plugins/npruntime.html#browseraccess>
717 WebBindings::retainObject(np_object);
718 void** v = static_cast<void**>(value);
726 #if !defined(OS_MACOSX) // OS X doesn't have windowed plugins.
727 case NPNVnetscapeWindow: {
728 scoped_refptr<PluginInstance> plugin = FindInstance(id);
731 return NPERR_INVALID_INSTANCE_ERROR;
733 gfx::PluginWindowHandle handle = plugin->window_handle();
734 *((void**)value) = (void*)handle;
739 case NPNVjavascriptEnabledBool: {
740 // yes, JS is enabled.
741 *((void**)value) = (void*)1;
745 #if defined(TOOLKIT_GTK)
747 // Tell them we are GTK2. (The alternative is GTK 1.2.)
748 *reinterpret_cast<int*>(value) = NPNVGtk2;
752 case NPNVSupportsXEmbedBool:
753 *reinterpret_cast<NPBool*>(value) = true;
757 case NPNVSupportsWindowless: {
758 NPBool* supports_windowless = reinterpret_cast<NPBool*>(value);
759 *supports_windowless = true;
763 case NPNVprivateModeBool: {
764 NPBool* private_mode = reinterpret_cast<NPBool*>(value);
765 scoped_refptr<PluginInstance> plugin(FindInstance(id));
768 return NPERR_INVALID_INSTANCE_ERROR;
770 *private_mode = plugin->webplugin()->IsOffTheRecord();
774 #if defined(OS_MACOSX)
775 case NPNVpluginDrawingModel: {
776 // return the drawing model that was negotiated when we initialized.
777 scoped_refptr<PluginInstance> plugin(FindInstance(id));
780 return NPERR_INVALID_INSTANCE_ERROR;
782 *reinterpret_cast<int*>(value) = plugin->drawing_model();
786 case NPNVsupportsCoreGraphicsBool:
787 case NPNVsupportsCocoaBool: {
788 // These drawing and event models are always supported.
789 NPBool* supports_model = reinterpret_cast<NPBool*>(value);
790 *supports_model = true;
794 case NPNVsupportsInvalidatingCoreAnimationBool:
795 case NPNVsupportsCoreAnimationBool: {
796 NPBool* supports_model = reinterpret_cast<NPBool*>(value);
797 *supports_model = content::SupportsCoreAnimationPlugins();
802 case NPNVsupportsCarbonBool:
804 #ifndef NP_NO_QUICKDRAW
805 case NPNVsupportsQuickDrawBool:
807 case NPNVsupportsOpenGLBool: {
808 // These models are never supported. OpenGL was never widely supported,
809 // and QuickDraw and Carbon have been deprecated for quite some time.
810 NPBool* supports_model = reinterpret_cast<NPBool*>(value);
811 *supports_model = false;
815 case NPNVsupportsCompositingCoreAnimationPluginsBool: {
816 NPBool* supports_compositing = reinterpret_cast<NPBool*>(value);
817 *supports_compositing = content::SupportsCoreAnimationPlugins();
821 case NPNVsupportsUpdatedCocoaTextInputBool: {
822 // We support the clarifications to the Cocoa IME event spec.
823 NPBool* supports_update = reinterpret_cast<NPBool*>(value);
824 *supports_update = true;
830 DVLOG(1) << "NPN_GetValue(" << variable << ") is not implemented yet.";
836 NPError NPN_SetValue(NPP id, NPPVariable variable, void* value) {
837 // Allows the plugin to set various modes
839 scoped_refptr<PluginInstance> plugin(FindInstance(id));
842 return NPERR_INVALID_INSTANCE_ERROR;
845 case NPPVpluginWindowBool: {
846 // Sets windowless mode for display of the plugin
847 // Note: the documentation at
848 // http://developer.mozilla.org/en/docs/NPN_SetValue is wrong. When
849 // value is NULL, the mode is set to true. This is the same way Mozilla
851 plugin->set_windowless(value == 0);
852 return NPERR_NO_ERROR;
854 case NPPVpluginTransparentBool: {
855 // Sets transparent mode for display of the plugin
857 // Transparent plugins require the browser to paint the background
858 // before having the plugin paint. By default, windowless plugins
859 // are transparent. Making a windowless plugin opaque means that
860 // the plugin does not require the browser to paint the background.
861 bool mode = (value != 0);
862 plugin->set_transparent(mode);
863 return NPERR_NO_ERROR;
865 case NPPVjavascriptPushCallerBool:
866 // Specifies whether you are pushing or popping the JSContext off.
868 // TODO: implement me
869 DVLOG(1) << "NPN_SetValue(NPPVJavascriptPushCallerBool) is not "
871 return NPERR_GENERIC_ERROR;
872 case NPPVpluginKeepLibraryInMemory:
873 // Tells browser that plugin library should live longer than usual.
874 // TODO: implement me
875 DVLOG(1) << "NPN_SetValue(NPPVpluginKeepLibraryInMemory) is not "
877 return NPERR_GENERIC_ERROR;
878 #if defined(OS_MACOSX)
879 case NPPVpluginDrawingModel: {
880 intptr_t model = reinterpret_cast<intptr_t>(value);
881 if (model == NPDrawingModelCoreGraphics ||
882 ((model == NPDrawingModelInvalidatingCoreAnimation ||
883 model == NPDrawingModelCoreAnimation) &&
884 content::SupportsCoreAnimationPlugins())) {
885 plugin->set_drawing_model(static_cast<NPDrawingModel>(model));
886 return NPERR_NO_ERROR;
888 return NPERR_GENERIC_ERROR;
890 case NPPVpluginEventModel: {
891 // Only the Cocoa event model is supported.
892 intptr_t model = reinterpret_cast<intptr_t>(value);
893 if (model == NPEventModelCocoa) {
894 plugin->set_event_model(static_cast<NPEventModel>(model));
895 return NPERR_NO_ERROR;
897 return NPERR_GENERIC_ERROR;
901 // TODO: implement me
902 DVLOG(1) << "NPN_SetValue(" << variable << ") is not implemented.";
907 return NPERR_GENERIC_ERROR;
910 void* NPN_GetJavaEnv() {
911 // TODO: implement me
912 DVLOG(1) << "NPN_GetJavaEnv is not implemented.";
916 void* NPN_GetJavaPeer(NPP) {
917 // TODO: implement me
918 DVLOG(1) << "NPN_GetJavaPeer is not implemented.";
922 void NPN_PushPopupsEnabledState(NPP id, NPBool enabled) {
923 scoped_refptr<PluginInstance> plugin(FindInstance(id));
925 plugin->PushPopupsEnabledState(enabled ? true : false);
928 void NPN_PopPopupsEnabledState(NPP id) {
929 scoped_refptr<PluginInstance> plugin(FindInstance(id));
931 plugin->PopPopupsEnabledState();
934 void NPN_PluginThreadAsyncCall(NPP id,
937 scoped_refptr<PluginInstance> plugin(FindInstance(id));
939 plugin->PluginThreadAsyncCall(func, user_data);
942 NPError NPN_GetValueForURL(NPP id,
943 NPNURLVariable variable,
948 return NPERR_INVALID_PARAM;
950 if (!url || !*url || !len)
951 return NPERR_INVALID_URL;
959 scoped_refptr<PluginInstance> plugin(FindInstance(id));
961 return NPERR_GENERIC_ERROR;
963 WebPlugin* webplugin = plugin->webplugin();
965 return NPERR_GENERIC_ERROR;
967 if (!webplugin->FindProxyForUrl(GURL(std::string(url)), &result))
968 return NPERR_GENERIC_ERROR;
971 case NPNURLVCookie: {
972 scoped_refptr<PluginInstance> plugin(FindInstance(id));
974 return NPERR_GENERIC_ERROR;
976 WebPlugin* webplugin = plugin->webplugin();
978 return NPERR_GENERIC_ERROR;
980 // Bypass third-party cookie blocking by using the url as the
981 // first_party_for_cookies.
982 GURL cookies_url((std::string(url)));
983 result = webplugin->GetCookies(cookies_url, cookies_url);
987 return NPERR_GENERIC_ERROR;
990 // Allocate this using the NPAPI allocator. The plugin will call
991 // NPN_Free to free this.
992 *value = static_cast<char*>(NPN_MemAlloc(result.length() + 1));
993 base::strlcpy(*value, result.c_str(), result.length() + 1);
994 *len = result.length();
996 return NPERR_NO_ERROR;
999 NPError NPN_SetValueForURL(NPP id,
1000 NPNURLVariable variable,
1005 return NPERR_INVALID_PARAM;
1008 return NPERR_INVALID_URL;
1011 case NPNURLVCookie: {
1012 scoped_refptr<PluginInstance> plugin(FindInstance(id));
1014 return NPERR_GENERIC_ERROR;
1016 WebPlugin* webplugin = plugin->webplugin();
1018 return NPERR_GENERIC_ERROR;
1020 std::string cookie(value, len);
1021 GURL cookies_url((std::string(url)));
1022 webplugin->SetCookie(cookies_url, cookies_url, cookie);
1023 return NPERR_NO_ERROR;
1026 // We don't support setting proxy values, fall through...
1029 // Fall through and return an error...
1033 return NPERR_GENERIC_ERROR;
1036 NPError NPN_GetAuthenticationInfo(NPP id,
1037 const char* protocol,
1046 if (!id || !protocol || !host || !scheme || !realm || !username ||
1047 !ulen || !password || !plen)
1048 return NPERR_INVALID_PARAM;
1050 // TODO: implement me (bug 23928)
1051 return NPERR_GENERIC_ERROR;
1054 uint32_t NPN_ScheduleTimer(NPP id,
1057 void (*func)(NPP id, uint32_t timer_id)) {
1058 scoped_refptr<PluginInstance> plugin(FindInstance(id));
1062 return plugin->ScheduleTimer(interval, repeat, func);
1065 void NPN_UnscheduleTimer(NPP id, uint32_t timer_id) {
1066 scoped_refptr<PluginInstance> plugin(FindInstance(id));
1068 plugin->UnscheduleTimer(timer_id);
1071 NPError NPN_PopUpContextMenu(NPP id, NPMenu* menu) {
1073 return NPERR_INVALID_PARAM;
1075 scoped_refptr<PluginInstance> plugin(FindInstance(id));
1077 return plugin->PopUpContextMenu(menu);
1080 return NPERR_GENERIC_ERROR;
1083 NPBool NPN_ConvertPoint(NPP id, double sourceX, double sourceY,
1084 NPCoordinateSpace sourceSpace,
1085 double *destX, double *destY,
1086 NPCoordinateSpace destSpace) {
1087 scoped_refptr<PluginInstance> plugin(FindInstance(id));
1089 return plugin->ConvertPoint(
1090 sourceX, sourceY, sourceSpace, destX, destY, destSpace);
1096 NPBool NPN_HandleEvent(NPP id, void *event, NPBool handled) {
1097 // TODO: Implement advanced key handling: http://crbug.com/46578
1102 NPBool NPN_UnfocusInstance(NPP id, NPFocusDirection direction) {
1103 // TODO: Implement advanced key handling: http://crbug.com/46578
1108 void NPN_URLRedirectResponse(NPP instance, void* notify_data, NPBool allow) {
1109 scoped_refptr<PluginInstance> plugin(FindInstance(instance));
1111 plugin->URLRedirectResponse(!!allow, notify_data);