Index: webkit/glue/plugins/plugin_host.cc |
=================================================================== |
--- webkit/glue/plugins/plugin_host.cc (revision 69426) |
+++ webkit/glue/plugins/plugin_host.cc (working copy) |
@@ -1,1111 +0,0 @@ |
-// Copyright (c) 2010 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "webkit/glue/plugins/plugin_host.h" |
- |
-#include "base/file_util.h" |
-#include "base/logging.h" |
-#include "base/scoped_ptr.h" |
-#include "base/string_piece.h" |
-#include "base/string_util.h" |
-#if defined(OS_MACOSX) |
-#include "base/sys_info.h" |
-#endif |
-#include "base/sys_string_conversions.h" |
-#include "base/utf_string_conversions.h" |
-#include "net/base/net_util.h" |
-#include "third_party/npapi/bindings/npapi_extensions.h" |
-#include "third_party/npapi/bindings/npruntime.h" |
-#include "third_party/WebKit/WebKit/chromium/public/WebBindings.h" |
-#include "third_party/WebKit/WebKit/chromium/public/WebKit.h" |
-#include "webkit/glue/webkit_glue.h" |
-#include "webkit/glue/plugins/default_plugin_shared.h" |
-#include "webkit/glue/plugins/npapi_extension_thunk.h" |
-#include "webkit/glue/plugins/plugin_instance.h" |
-#include "webkit/glue/plugins/plugin_lib.h" |
-#include "webkit/glue/plugins/plugin_list.h" |
-#include "webkit/glue/plugins/plugin_stream_url.h" |
-#include "webkit/glue/plugins/webplugin_delegate.h" |
-#include "webkit/glue/plugins/webplugininfo.h" |
- |
-using WebKit::WebBindings; |
- |
-// Finds a PluginInstance from an NPP. |
-// The caller must take a reference if needed. |
-static NPAPI::PluginInstance* FindInstance(NPP id) { |
- if (id == NULL) { |
- return NULL; |
- } |
- return reinterpret_cast<NPAPI::PluginInstance*>(id->ndata); |
-} |
- |
-#if defined(OS_MACOSX) |
-// Returns true if the OS supports shared accelerated surfaces via IOSurface. |
-// This is true on Snow Leopard and higher. |
-static bool SupportsSharingAcceleratedSurfaces() { |
- int32 major, minor, bugfix; |
- base::SysInfo::OperatingSystemVersionNumbers(&major, &minor, &bugfix); |
- return major > 10 || (major == 10 && minor > 5); |
-} |
-#endif |
- |
-namespace NPAPI { |
- |
-scoped_refptr<PluginHost> PluginHost::singleton_; |
- |
-PluginHost::PluginHost() { |
- InitializeHostFuncs(); |
-} |
- |
-PluginHost::~PluginHost() { |
-} |
- |
-PluginHost *PluginHost::Singleton() { |
- if (singleton_.get() == NULL) { |
- singleton_ = new PluginHost(); |
- } |
- |
- DCHECK(singleton_.get() != NULL); |
- return singleton_; |
-} |
- |
-void PluginHost::InitializeHostFuncs() { |
- memset(&host_funcs_, 0, sizeof(host_funcs_)); |
- host_funcs_.size = sizeof(host_funcs_); |
- host_funcs_.version = (NP_VERSION_MAJOR << 8) | (NP_VERSION_MINOR); |
- |
- // The "basic" functions |
- host_funcs_.geturl = &NPN_GetURL; |
- host_funcs_.posturl = &NPN_PostURL; |
- host_funcs_.requestread = &NPN_RequestRead; |
- host_funcs_.newstream = &NPN_NewStream; |
- host_funcs_.write = &NPN_Write; |
- host_funcs_.destroystream = &NPN_DestroyStream; |
- host_funcs_.status = &NPN_Status; |
- host_funcs_.uagent = &NPN_UserAgent; |
- host_funcs_.memalloc = &NPN_MemAlloc; |
- host_funcs_.memfree = &NPN_MemFree; |
- host_funcs_.memflush = &NPN_MemFlush; |
- host_funcs_.reloadplugins = &NPN_ReloadPlugins; |
- |
- // We don't implement java yet |
- host_funcs_.getJavaEnv = &NPN_GetJavaEnv; |
- host_funcs_.getJavaPeer = &NPN_GetJavaPeer; |
- |
- // Advanced functions we implement |
- host_funcs_.geturlnotify = &NPN_GetURLNotify; |
- host_funcs_.posturlnotify = &NPN_PostURLNotify; |
- host_funcs_.getvalue = &NPN_GetValue; |
- host_funcs_.setvalue = &NPN_SetValue; |
- host_funcs_.invalidaterect = &NPN_InvalidateRect; |
- host_funcs_.invalidateregion = &NPN_InvalidateRegion; |
- host_funcs_.forceredraw = &NPN_ForceRedraw; |
- |
- // These come from the Javascript Engine |
- host_funcs_.getstringidentifier = WebBindings::getStringIdentifier; |
- host_funcs_.getstringidentifiers = WebBindings::getStringIdentifiers; |
- host_funcs_.getintidentifier = WebBindings::getIntIdentifier; |
- host_funcs_.identifierisstring = WebBindings::identifierIsString; |
- host_funcs_.utf8fromidentifier = WebBindings::utf8FromIdentifier; |
- host_funcs_.intfromidentifier = WebBindings::intFromIdentifier; |
- host_funcs_.createobject = WebBindings::createObject; |
- host_funcs_.retainobject = WebBindings::retainObject; |
- host_funcs_.releaseobject = WebBindings::releaseObject; |
- host_funcs_.invoke = WebBindings::invoke; |
- host_funcs_.invokeDefault = WebBindings::invokeDefault; |
- host_funcs_.evaluate = WebBindings::evaluate; |
- host_funcs_.getproperty = WebBindings::getProperty; |
- host_funcs_.setproperty = WebBindings::setProperty; |
- host_funcs_.removeproperty = WebBindings::removeProperty; |
- host_funcs_.hasproperty = WebBindings::hasProperty; |
- host_funcs_.hasmethod = WebBindings::hasMethod; |
- host_funcs_.releasevariantvalue = WebBindings::releaseVariantValue; |
- host_funcs_.setexception = WebBindings::setException; |
- host_funcs_.pushpopupsenabledstate = NPN_PushPopupsEnabledState; |
- host_funcs_.poppopupsenabledstate = NPN_PopPopupsEnabledState; |
- host_funcs_.enumerate = WebBindings::enumerate; |
- host_funcs_.pluginthreadasynccall = NPN_PluginThreadAsyncCall; |
- host_funcs_.construct = WebBindings::construct; |
- host_funcs_.getvalueforurl = NPN_GetValueForURL; |
- host_funcs_.setvalueforurl = NPN_SetValueForURL; |
- host_funcs_.getauthenticationinfo = NPN_GetAuthenticationInfo; |
- host_funcs_.scheduletimer = NPN_ScheduleTimer; |
- host_funcs_.unscheduletimer = NPN_UnscheduleTimer; |
- host_funcs_.popupcontextmenu = NPN_PopUpContextMenu; |
- host_funcs_.convertpoint = NPN_ConvertPoint; |
- host_funcs_.handleevent = NPN_HandleEvent; |
- host_funcs_.unfocusinstance = NPN_UnfocusInstance; |
- host_funcs_.urlredirectresponse = NPN_URLRedirectResponse; |
-} |
- |
-void PluginHost::PatchNPNetscapeFuncs(NPNetscapeFuncs* overrides) { |
- // When running in the plugin process, we need to patch the NPN functions |
- // that the plugin calls to interact with NPObjects that we give. Otherwise |
- // the plugin will call the v8 NPN functions, which won't work since we have |
- // an NPObjectProxy and not a real v8 implementation. |
- if (overrides->invoke) |
- host_funcs_.invoke = overrides->invoke; |
- |
- if (overrides->invokeDefault) |
- host_funcs_.invokeDefault = overrides->invokeDefault; |
- |
- if (overrides->evaluate) |
- host_funcs_.evaluate = overrides->evaluate; |
- |
- if (overrides->getproperty) |
- host_funcs_.getproperty = overrides->getproperty; |
- |
- if (overrides->setproperty) |
- host_funcs_.setproperty = overrides->setproperty; |
- |
- if (overrides->removeproperty) |
- host_funcs_.removeproperty = overrides->removeproperty; |
- |
- if (overrides->hasproperty) |
- host_funcs_.hasproperty = overrides->hasproperty; |
- |
- if (overrides->hasmethod) |
- host_funcs_.hasmethod = overrides->hasmethod; |
- |
- if (overrides->setexception) |
- host_funcs_.setexception = overrides->setexception; |
- |
- if (overrides->enumerate) |
- host_funcs_.enumerate = overrides->enumerate; |
-} |
- |
-bool PluginHost::SetPostData(const char* buf, |
- uint32 length, |
- std::vector<std::string>* names, |
- std::vector<std::string>* values, |
- std::vector<char>* body) { |
- // Use a state table to do the parsing. Whitespace must be |
- // trimmed after the fact if desired. In our case, we actually |
- // don't care about the whitespace, because we're just going to |
- // pass this back into another POST. This function strips out the |
- // "Content-length" header and does not append it to the request. |
- |
- // |
- // This parser takes action only on state changes. |
- // |
- // Transition table: |
- // : \n NULL Other |
- // 0 GetHeader 1 2 4 0 |
- // 1 GetValue 1 0 3 1 |
- // 2 GetData 2 2 3 2 |
- // 3 DONE |
- // 4 ERR |
- // |
- enum { INPUT_COLON=0, INPUT_NEWLINE, INPUT_NULL, INPUT_OTHER }; |
- enum { GETNAME, GETVALUE, GETDATA, DONE, ERR }; |
- int statemachine[3][4] = { { GETVALUE, GETDATA, GETDATA, GETNAME }, |
- { GETVALUE, GETNAME, DONE, GETVALUE }, |
- { GETDATA, GETDATA, DONE, GETDATA } }; |
- std::string name, value; |
- const char* ptr = static_cast<const char*>(buf); |
- const char* start = ptr; |
- int state = GETNAME; // initial state |
- bool done = false; |
- bool err = false; |
- do { |
- int input; |
- |
- // Translate the current character into an input |
- // for the state table. |
- switch (*ptr) { |
- case ':' : |
- input = INPUT_COLON; |
- break; |
- case '\n': |
- input = INPUT_NEWLINE; |
- break; |
- case 0 : |
- input = INPUT_NULL; |
- break; |
- default : |
- input = INPUT_OTHER; |
- break; |
- } |
- |
- int newstate = statemachine[state][input]; |
- |
- // Take action based on the new state. |
- if (state != newstate) { |
- switch (newstate) { |
- case GETNAME: |
- // Got a value. |
- value = std::string(start, ptr - start); |
- TrimWhitespace(value, TRIM_ALL, &value); |
- // If the name field is empty, we'll skip this header |
- // but we won't error out. |
- if (!name.empty() && name != "content-length") { |
- names->push_back(name); |
- values->push_back(value); |
- } |
- start = ptr + 1; |
- break; |
- case GETVALUE: |
- // Got a header. |
- name = StringToLowerASCII(std::string(start, ptr - start)); |
- TrimWhitespace(name, TRIM_ALL, &name); |
- start = ptr + 1; |
- break; |
- case GETDATA: { |
- // Finished headers, now get body |
- if (*ptr) |
- start = ptr + 1; |
- size_t previous_size = body->size(); |
- size_t new_body_size = length - static_cast<int>(start - buf); |
- body->resize(previous_size + new_body_size); |
- if (!body->empty()) |
- memcpy(&body->front() + previous_size, start, new_body_size); |
- done = true; |
- break; |
- } |
- case ERR: |
- // error |
- err = true; |
- done = true; |
- break; |
- } |
- } |
- state = newstate; |
- ptr++; |
- } while (!done); |
- |
- return !err; |
-} |
- |
-} // namespace NPAPI |
- |
-extern "C" { |
- |
-// Allocates memory from the host's memory space. |
-void* NPN_MemAlloc(uint32_t size) { |
- scoped_refptr<NPAPI::PluginHost> host(NPAPI::PluginHost::Singleton()); |
- if (host != NULL) { |
- // Note: We must use the same allocator/deallocator |
- // that is used by the javascript library, as some of the |
- // JS APIs will pass memory to the plugin which the plugin |
- // will attempt to free. |
- return malloc(size); |
- } |
- return NULL; |
-} |
- |
-// Deallocates memory from the host's memory space |
-void NPN_MemFree(void* ptr) { |
- scoped_refptr<NPAPI::PluginHost> host(NPAPI::PluginHost::Singleton()); |
- if (host != NULL) { |
- if (ptr != NULL && ptr != reinterpret_cast<void*>(-1)) |
- free(ptr); |
- } |
-} |
- |
-// Requests that the host free a specified amount of memory. |
-uint32_t NPN_MemFlush(uint32_t size) { |
- // This is not relevant on Windows; MAC specific |
- return size; |
-} |
- |
-// This is for dynamic discovery of new plugins. |
-// Should force a re-scan of the plugins directory to load new ones. |
-void NPN_ReloadPlugins(NPBool reload_pages) { |
- WebKit::resetPluginCache(reload_pages ? true : false); |
-} |
- |
-// Requests a range of bytes for a seekable stream. |
-NPError NPN_RequestRead(NPStream* stream, NPByteRange* range_list) { |
- if (!stream || !range_list) |
- return NPERR_GENERIC_ERROR; |
- |
- scoped_refptr<NPAPI::PluginInstance> plugin( |
- reinterpret_cast<NPAPI::PluginInstance*>(stream->ndata)); |
- if (!plugin.get()) |
- return NPERR_GENERIC_ERROR; |
- |
- plugin->RequestRead(stream, range_list); |
- return NPERR_NO_ERROR; |
-} |
- |
-// Generic form of GetURL for common code between GetURL and GetURLNotify. |
-static NPError GetURLNotify(NPP id, |
- const char* url, |
- const char* target, |
- bool notify, |
- void* notify_data) { |
- if (!url) |
- return NPERR_INVALID_URL; |
- |
- scoped_refptr<NPAPI::PluginInstance> plugin(FindInstance(id)); |
- if (!plugin.get()) { |
- return NPERR_GENERIC_ERROR; |
- } |
- |
- plugin->RequestURL(url, "GET", target, NULL, 0, notify, notify_data); |
- return NPERR_NO_ERROR; |
-} |
- |
-// Requests creation of a new stream with the contents of the |
-// specified URL; gets notification of the result. |
-NPError NPN_GetURLNotify(NPP id, |
- const char* url, |
- const char* target, |
- void* notify_data) { |
- // This is identical to NPN_GetURL, but after finishing, the |
- // browser will call NPP_URLNotify to inform the plugin that |
- // it has completed. |
- |
- // According to the NPAPI documentation, if target == _self |
- // or a parent to _self, the browser should return NPERR_INVALID_PARAM, |
- // because it can't notify the plugin once deleted. This is |
- // absolutely false; firefox doesn't do this, and Flash relies on |
- // being able to use this. |
- |
- // Also according to the NPAPI documentation, we should return |
- // NPERR_INVALID_URL if the url requested is not valid. However, |
- // this would require that we synchronously start fetching the |
- // URL. That just isn't practical. As such, there really is |
- // no way to return this error. From looking at the Firefox |
- // implementation, it doesn't look like Firefox does this either. |
- |
- return GetURLNotify(id, url, target, true, notify_data); |
-} |
- |
-NPError NPN_GetURL(NPP id, const char* url, const char* target) { |
- // Notes: |
- // Request from the Plugin to fetch content either for the plugin |
- // or to be placed into a browser window. |
- // |
- // If target == null, the browser fetches content and streams to plugin. |
- // otherwise, the browser loads content into an existing browser frame. |
- // If the target is the window/frame containing the plugin, the plugin |
- // may be destroyed. |
- // If the target is _blank, a mailto: or news: url open content in a new |
- // browser window |
- // If the target is _self, no other instance of the plugin is created. The |
- // plugin continues to operate in its own window |
- |
- return GetURLNotify(id, url, target, false, 0); |
-} |
- |
-// Generic form of PostURL for common code between PostURL and PostURLNotify. |
-static NPError PostURLNotify(NPP id, |
- const char* url, |
- const char* target, |
- uint32_t len, |
- const char* buf, |
- NPBool file, |
- bool notify, |
- void* notify_data) { |
- if (!url) |
- return NPERR_INVALID_URL; |
- |
- scoped_refptr<NPAPI::PluginInstance> plugin(FindInstance(id)); |
- if (!plugin.get()) { |
- NOTREACHED(); |
- return NPERR_GENERIC_ERROR; |
- } |
- |
- std::string post_file_contents; |
- |
- if (file) { |
- // Post data to be uploaded from a file. This can be handled in two |
- // ways. |
- // 1. Read entire file and send the contents as if it was a post data |
- // specified in the argument |
- // 2. Send just the file details and read them in the browser at the |
- // time of sending the request. |
- // Approach 2 is more efficient but complicated. Approach 1 has a major |
- // drawback of sending potentially large data over two IPC hops. In a way |
- // 'large data over IPC' problem exists as it is in case of plugin giving |
- // the data directly instead of in a file. |
- // Currently we are going with the approach 1 to get the feature working. |
- // We can optimize this later with approach 2. |
- |
- // TODO(joshia): Design a scheme to send a file descriptor instead of |
- // entire file contents across. |
- |
- // Security alert: |
- // --------------- |
- // Here we are blindly uploading whatever file requested by a plugin. |
- // This is risky as someone could exploit a plugin to send private |
- // data in arbitrary locations. |
- // A malicious (non-sandboxed) plugin has unfeterred access to OS |
- // resources and can do this anyway without using browser's HTTP stack. |
- // FWIW, Firefox and Safari don't perform any security checks. |
- |
- if (!buf) |
- return NPERR_FILE_NOT_FOUND; |
- |
- std::string file_path_ascii(buf); |
- FilePath file_path; |
- static const char kFileUrlPrefix[] = "file:"; |
- if (StartsWithASCII(file_path_ascii, kFileUrlPrefix, false)) { |
- GURL file_url(file_path_ascii); |
- DCHECK(file_url.SchemeIsFile()); |
- net::FileURLToFilePath(file_url, &file_path); |
- } else { |
- file_path = FilePath::FromWStringHack( |
- base::SysNativeMBToWide(file_path_ascii)); |
- } |
- |
- base::PlatformFileInfo post_file_info = {0}; |
- if (!file_util::GetFileInfo(file_path, &post_file_info) || |
- post_file_info.is_directory) |
- return NPERR_FILE_NOT_FOUND; |
- |
- if (!file_util::ReadFileToString(file_path, &post_file_contents)) |
- return NPERR_FILE_NOT_FOUND; |
- |
- buf = post_file_contents.c_str(); |
- len = post_file_contents.size(); |
- } |
- |
- // The post data sent by a plugin contains both headers |
- // and post data. Example: |
- // Content-type: text/html |
- // Content-length: 200 |
- // |
- // <200 bytes of content here> |
- // |
- // Unfortunately, our stream needs these broken apart, |
- // so we need to parse the data and set headers and data |
- // separately. |
- plugin->RequestURL(url, "POST", target, buf, len, notify, notify_data); |
- return NPERR_NO_ERROR; |
-} |
- |
-NPError NPN_PostURLNotify(NPP id, |
- const char* url, |
- const char* target, |
- uint32_t len, |
- const char* buf, |
- NPBool file, |
- void* notify_data) { |
- return PostURLNotify(id, url, target, len, buf, file, true, notify_data); |
-} |
- |
-NPError NPN_PostURL(NPP id, |
- const char* url, |
- const char* target, |
- uint32_t len, |
- const char* buf, |
- NPBool file) { |
- // POSTs data to an URL, either from a temp file or a buffer. |
- // If file is true, buf contains a temp file (which host will delete after |
- // completing), and len contains the length of the filename. |
- // If file is false, buf contains the data to send, and len contains the |
- // length of the buffer |
- // |
- // If target is null, |
- // server response is returned to the plugin |
- // If target is _current, _self, or _top, |
- // server response is written to the plugin window and plugin is unloaded. |
- // If target is _new or _blank, |
- // server response is written to a new browser window |
- // If target is an existing frame, |
- // server response goes to that frame. |
- // |
- // For protocols other than FTP |
- // file uploads must be line-end converted from \r\n to \n |
- // |
- // Note: you cannot specify headers (even a blank line) in a memory buffer, |
- // use NPN_PostURLNotify |
- |
- return PostURLNotify(id, url, target, len, buf, file, false, 0); |
-} |
- |
-NPError NPN_NewStream(NPP id, |
- NPMIMEType type, |
- const char* target, |
- NPStream** stream) { |
- // Requests creation of a new data stream produced by the plugin, |
- // consumed by the browser. |
- // |
- // Browser should put this stream into a window target. |
- // |
- // TODO: implement me |
- DVLOG(1) << "NPN_NewStream is not implemented yet."; |
- return NPERR_GENERIC_ERROR; |
-} |
- |
-int32_t NPN_Write(NPP id, NPStream* stream, int32_t len, void* buffer) { |
- // Writes data to an existing Plugin-created stream. |
- |
- // TODO: implement me |
- DVLOG(1) << "NPN_Write is not implemented yet."; |
- return NPERR_GENERIC_ERROR; |
-} |
- |
-NPError NPN_DestroyStream(NPP id, NPStream* stream, NPReason reason) { |
- // Destroys a stream (could be created by plugin or browser). |
- // |
- // Reasons: |
- // NPRES_DONE - normal completion |
- // NPRES_USER_BREAK - user terminated |
- // NPRES_NETWORK_ERROR - network error (all errors fit here?) |
- // |
- // |
- |
- scoped_refptr<NPAPI::PluginInstance> plugin(FindInstance(id)); |
- if (plugin.get() == NULL) { |
- NOTREACHED(); |
- return NPERR_GENERIC_ERROR; |
- } |
- |
- return plugin->NPP_DestroyStream(stream, reason); |
-} |
- |
-const char* NPN_UserAgent(NPP id) { |
-#if defined(OS_WIN) |
- // Flash passes in a null id during the NP_initialize call. We need to |
- // default to the Mozilla user agent if we don't have an NPP instance or |
- // else Flash won't request windowless mode. |
- bool use_mozilla_user_agent = true; |
- if (id) { |
- scoped_refptr<NPAPI::PluginInstance> plugin = FindInstance(id); |
- if (plugin.get() && !plugin->use_mozilla_user_agent()) |
- use_mozilla_user_agent = false; |
- } |
- |
- if (use_mozilla_user_agent) |
- return "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9a1) " |
- "Gecko/20061103 Firefox/2.0a1"; |
-#elif defined(OS_MACOSX) |
- // Silverlight 4 doesn't handle events correctly unless we claim to be Safari. |
- scoped_refptr<NPAPI::PluginInstance> plugin; |
- if (id) |
- plugin = FindInstance(id); |
- if (plugin.get()) { |
- WebPluginInfo plugin_info = plugin->plugin_lib()->plugin_info(); |
- if (plugin_info.name == ASCIIToUTF16("Silverlight Plug-In") && |
- StartsWith(plugin_info.version, ASCIIToUTF16("4."), false)) { |
- return "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-us) " |
- "AppleWebKit/534.1+ (KHTML, like Gecko) Version/5.0 Safari/533.16"; |
- } |
- } |
-#endif |
- |
- return webkit_glue::GetUserAgent(GURL()).c_str(); |
-} |
- |
-void NPN_Status(NPP id, const char* message) { |
- // Displays a message on the status line of the browser window. |
- |
- // TODO: implement me |
- DVLOG(1) << "NPN_Status is not implemented yet."; |
-} |
- |
-void NPN_InvalidateRect(NPP id, NPRect *invalidRect) { |
- // Invalidates specified drawing area prior to repainting or refreshing a |
- // windowless plugin |
- |
- // Before a windowless plugin can refresh part of its drawing area, it must |
- // first invalidate it. This function causes the NPP_HandleEvent method to |
- // pass an update event or a paint message to the plug-in. After calling |
- // this method, the plug-in recieves a paint message asynchronously. |
- |
- // The browser redraws invalid areas of the document and any windowless |
- // plug-ins at regularly timed intervals. To force a paint message, the |
- // plug-in can call NPN_ForceRedraw after calling this method. |
- |
- scoped_refptr<NPAPI::PluginInstance> plugin(FindInstance(id)); |
- if (plugin.get() && plugin->webplugin()) { |
- if (invalidRect) { |
-#if defined(OS_WIN) |
- if (!plugin->windowless()) { |
- RECT rect = {0}; |
- rect.left = invalidRect->left; |
- rect.right = invalidRect->right; |
- rect.top = invalidRect->top; |
- rect.bottom = invalidRect->bottom; |
- ::InvalidateRect(plugin->window_handle(), &rect, false); |
- return; |
- } |
-#endif |
- gfx::Rect rect(invalidRect->left, |
- invalidRect->top, |
- invalidRect->right - invalidRect->left, |
- invalidRect->bottom - invalidRect->top); |
- plugin->webplugin()->InvalidateRect(rect); |
- } else { |
- plugin->webplugin()->Invalidate(); |
- } |
- } |
-} |
- |
-void NPN_InvalidateRegion(NPP id, NPRegion invalidRegion) { |
- // Invalidates a specified drawing region prior to repainting |
- // or refreshing a window-less plugin. |
- // |
- // Similar to NPN_InvalidateRect. |
- |
- // TODO: this is overkill--add platform-specific region handling (at the |
- // very least, fetch the region's bounding box and pass it to InvalidateRect). |
- scoped_refptr<NPAPI::PluginInstance> plugin(FindInstance(id)); |
- DCHECK(plugin.get() != NULL); |
- if (plugin.get() && plugin->webplugin()) |
- plugin->webplugin()->Invalidate(); |
-} |
- |
-void NPN_ForceRedraw(NPP id) { |
- // Forces repaint for a windowless plug-in. |
- // |
- // We deliberately do not implement this; we don't want plugins forcing |
- // synchronous paints. |
-} |
- |
-NPError NPN_GetValue(NPP id, NPNVariable variable, void* value) { |
- // Allows the plugin to query the browser for information |
- // |
- // Variables: |
- // NPNVxDisplay (unix only) |
- // NPNVxtAppContext (unix only) |
- // NPNVnetscapeWindow (win only) - Gets the native window on which the |
- // plug-in drawing occurs, returns HWND |
- // NPNVjavascriptEnabledBool: tells whether Javascript is enabled |
- // NPNVasdEnabledBool: tells whether SmartUpdate is enabled |
- // NPNVOfflineBool: tells whether offline-mode is enabled |
- |
- NPError rv = NPERR_GENERIC_ERROR; |
- |
- switch (static_cast<int>(variable)) { |
- case NPNVWindowNPObject: { |
- scoped_refptr<NPAPI::PluginInstance> plugin(FindInstance(id)); |
- NPObject *np_object = plugin->webplugin()->GetWindowScriptNPObject(); |
- // Return value is expected to be retained, as |
- // described here: |
- // <http://www.mozilla.org/projects/plugins/npruntime.html#browseraccess> |
- if (np_object) { |
- WebBindings::retainObject(np_object); |
- void **v = (void **)value; |
- *v = np_object; |
- rv = NPERR_NO_ERROR; |
- } else { |
- NOTREACHED(); |
- } |
- break; |
- } |
- case NPNVPluginElementNPObject: { |
- scoped_refptr<NPAPI::PluginInstance> plugin(FindInstance(id)); |
- NPObject *np_object = plugin->webplugin()->GetPluginElement(); |
- // Return value is expected to be retained, as |
- // described here: |
- // <http://www.mozilla.org/projects/plugins/npruntime.html#browseraccess> |
- if (np_object) { |
- WebBindings::retainObject(np_object); |
- void** v = static_cast<void**>(value); |
- *v = np_object; |
- rv = NPERR_NO_ERROR; |
- } else { |
- NOTREACHED(); |
- } |
- break; |
- } |
- #if !defined(OS_MACOSX) // OS X doesn't have windowed plugins. |
- case NPNVnetscapeWindow: { |
- scoped_refptr<NPAPI::PluginInstance> plugin = FindInstance(id); |
- if (!plugin.get()) { |
- NOTREACHED(); |
- return NPERR_GENERIC_ERROR; |
- } |
- gfx::PluginWindowHandle handle = plugin->window_handle(); |
- *((void**)value) = (void*)handle; |
- rv = NPERR_NO_ERROR; |
- break; |
- } |
- #endif |
- case NPNVjavascriptEnabledBool: { |
- // yes, JS is enabled. |
- *((void**)value) = (void*)1; |
- rv = NPERR_NO_ERROR; |
- break; |
- } |
- #if defined(TOOLKIT_USES_GTK) |
- case NPNVToolkit: |
- // Tell them we are GTK2. (The alternative is GTK 1.2.) |
- *reinterpret_cast<int*>(value) = NPNVGtk2; |
- rv = NPERR_NO_ERROR; |
- break; |
- |
- case NPNVSupportsXEmbedBool: |
- *reinterpret_cast<NPBool*>(value) = true; |
- rv = NPERR_NO_ERROR; |
- break; |
- #endif |
- case NPNVSupportsWindowless: { |
- NPBool* supports_windowless = reinterpret_cast<NPBool*>(value); |
- *supports_windowless = true; |
- rv = NPERR_NO_ERROR; |
- break; |
- } |
- case NPNVprivateModeBool: { |
- NPBool* private_mode = reinterpret_cast<NPBool*>(value); |
- scoped_refptr<NPAPI::PluginInstance> plugin(FindInstance(id)); |
- *private_mode = plugin->webplugin()->IsOffTheRecord(); |
- rv = NPERR_NO_ERROR; |
- break; |
- } |
- case default_plugin::kMissingPluginStatusStart + |
- default_plugin::MISSING_PLUGIN_AVAILABLE: |
- // fall through |
- case default_plugin::kMissingPluginStatusStart + |
- default_plugin::MISSING_PLUGIN_USER_STARTED_DOWNLOAD: { |
- // This is a hack for the default plugin to send notification to |
- // renderer. Even though we check if the plugin is the default plugin, |
- // we still need to worry about future standard change that may conflict |
- // with the variable definition, in order to avoid duplicate case clauses |
- // in this big switch statement. |
- scoped_refptr<NPAPI::PluginInstance> plugin(FindInstance(id)); |
- if (plugin->plugin_lib()->plugin_info().path.value() == |
- kDefaultPluginLibraryName) { |
- plugin->webplugin()->OnMissingPluginStatus( |
- variable - default_plugin::kMissingPluginStatusStart); |
- } |
- break; |
- } |
- #if defined(OS_MACOSX) |
- case NPNVpluginDrawingModel: { |
- // return the drawing model that was negotiated when we initialized. |
- scoped_refptr<NPAPI::PluginInstance> plugin(FindInstance(id)); |
- *reinterpret_cast<int*>(value) = plugin->drawing_model(); |
- rv = NPERR_NO_ERROR; |
- break; |
- } |
-#ifndef NP_NO_QUICKDRAW |
- case NPNVsupportsQuickDrawBool: { |
- // We do not admit to supporting the QuickDraw drawing model. The logic |
- // here is that our QuickDraw plugin support is so rudimentary that we |
- // only want to use it as a fallback to keep plugins from crashing: if a |
- // plugin knows enough to ask, we want them to use CoreGraphics. |
- NPBool* supports_qd = reinterpret_cast<NPBool*>(value); |
- *supports_qd = false; |
- rv = NPERR_NO_ERROR; |
- break; |
- } |
-#endif |
- case NPNVsupportsCoreGraphicsBool: |
-#ifndef NP_NO_CARBON |
- case NPNVsupportsCarbonBool: |
-#endif |
- case NPNVsupportsCocoaBool: { |
- // we do support these drawing and event models. |
- NPBool* supports_model = reinterpret_cast<NPBool*>(value); |
- *supports_model = true; |
- rv = NPERR_NO_ERROR; |
- break; |
- } |
- case NPNVsupportsCoreAnimationBool: { |
- // We only support the Core Animation model on 10.6 and higher |
- // TODO(stuartmorgan): Once existing CA plugins have implemented the |
- // invalidating version, remove support for this one. |
- NPBool* supports_model = reinterpret_cast<NPBool*>(value); |
- *supports_model = SupportsSharingAcceleratedSurfaces() ? true : false; |
- rv = NPERR_NO_ERROR; |
- break; |
- } |
- case NPNVsupportsInvalidatingCoreAnimationBool: { |
- NPBool* supports_model = reinterpret_cast<NPBool*>(value); |
- *supports_model = true; |
- rv = NPERR_NO_ERROR; |
- break; |
- } |
- case NPNVsupportsOpenGLBool: { |
- // This drawing model was never widely supported, and we don't plan to |
- // support it. |
- NPBool* supports_model = reinterpret_cast<NPBool*>(value); |
- *supports_model = false; |
- rv = NPERR_NO_ERROR; |
- break; |
- } |
- #endif // OS_MACOSX |
- case NPNVPepperExtensions: |
- // Available for any plugin that attempts to get it. |
- // If the plugin is not started in a Pepper implementation, it |
- // will likely fail when it tries to use any of the functions |
- // attached to the extension vector. |
- rv = NPAPI::GetPepperExtensionsFunctions(value); |
- break; |
- default: |
- DVLOG(1) << "NPN_GetValue(" << variable << ") is not implemented yet."; |
- break; |
- } |
- return rv; |
-} |
- |
-NPError NPN_SetValue(NPP id, NPPVariable variable, void* value) { |
- // Allows the plugin to set various modes |
- |
- scoped_refptr<NPAPI::PluginInstance> plugin(FindInstance(id)); |
- switch(variable) { |
- case NPPVpluginWindowBool: { |
- // Sets windowless mode for display of the plugin |
- // Note: the documentation at |
- // http://developer.mozilla.org/en/docs/NPN_SetValue is wrong. When |
- // value is NULL, the mode is set to true. This is the same way Mozilla |
- // works. |
- plugin->set_windowless(value == 0); |
- return NPERR_NO_ERROR; |
- } |
- case NPPVpluginTransparentBool: { |
- // Sets transparent mode for display of the plugin |
- // |
- // Transparent plugins require the browser to paint the background |
- // before having the plugin paint. By default, windowless plugins |
- // are transparent. Making a windowless plugin opaque means that |
- // the plugin does not require the browser to paint the background. |
- bool mode = (value != 0); |
- plugin->set_transparent(mode); |
- return NPERR_NO_ERROR; |
- } |
- case NPPVjavascriptPushCallerBool: |
- // Specifies whether you are pushing or popping the JSContext off. |
- // the stack |
- // TODO: implement me |
- DVLOG(1) << "NPN_SetValue(NPPVJavascriptPushCallerBool) is not " |
- "implemented."; |
- return NPERR_GENERIC_ERROR; |
- case NPPVpluginKeepLibraryInMemory: |
- // Tells browser that plugin library should live longer than usual. |
- // TODO: implement me |
- DVLOG(1) << "NPN_SetValue(NPPVpluginKeepLibraryInMemory) is not " |
- "implemented."; |
- return NPERR_GENERIC_ERROR; |
- #if defined(OS_MACOSX) |
- case NPPVpluginDrawingModel: { |
- int model = reinterpret_cast<int>(value); |
- if (model == NPDrawingModelCoreGraphics || |
- model == NPDrawingModelInvalidatingCoreAnimation || |
- (model == NPDrawingModelCoreAnimation && |
- SupportsSharingAcceleratedSurfaces())) { |
- plugin->set_drawing_model(static_cast<NPDrawingModel>(model)); |
- return NPERR_NO_ERROR; |
- } |
- return NPERR_GENERIC_ERROR; |
- } |
- case NPPVpluginEventModel: { |
- // we support Carbon and Cocoa event models |
- int model = reinterpret_cast<int>(value); |
- switch (model) { |
-#ifndef NP_NO_CARBON |
- case NPEventModelCarbon: |
-#endif |
- case NPEventModelCocoa: |
- plugin->set_event_model(static_cast<NPEventModel>(model)); |
- return NPERR_NO_ERROR; |
- break; |
- } |
- return NPERR_GENERIC_ERROR; |
- } |
- #endif |
- default: |
- // TODO: implement me |
- DVLOG(1) << "NPN_SetValue(" << variable << ") is not implemented."; |
- break; |
- } |
- |
- NOTREACHED(); |
- return NPERR_GENERIC_ERROR; |
-} |
- |
-void* NPN_GetJavaEnv() { |
- // TODO: implement me |
- DVLOG(1) << "NPN_GetJavaEnv is not implemented."; |
- return NULL; |
-} |
- |
-void* NPN_GetJavaPeer(NPP) { |
- // TODO: implement me |
- DVLOG(1) << "NPN_GetJavaPeer is not implemented."; |
- return NULL; |
-} |
- |
-void NPN_PushPopupsEnabledState(NPP id, NPBool enabled) { |
- scoped_refptr<NPAPI::PluginInstance> plugin(FindInstance(id)); |
- if (plugin) |
- plugin->PushPopupsEnabledState(enabled ? true : false); |
-} |
- |
-void NPN_PopPopupsEnabledState(NPP id) { |
- scoped_refptr<NPAPI::PluginInstance> plugin(FindInstance(id)); |
- if (plugin) |
- plugin->PopPopupsEnabledState(); |
-} |
- |
-void NPN_PluginThreadAsyncCall(NPP id, |
- void (*func)(void*), |
- void* user_data) { |
- scoped_refptr<NPAPI::PluginInstance> plugin(FindInstance(id)); |
- if (plugin) |
- plugin->PluginThreadAsyncCall(func, user_data); |
-} |
- |
-NPError NPN_GetValueForURL(NPP id, |
- NPNURLVariable variable, |
- const char* url, |
- char** value, |
- uint32_t* len) { |
- if (!id) |
- return NPERR_INVALID_PARAM; |
- |
- if (!url || !*url || !len) |
- return NPERR_INVALID_URL; |
- |
- *len = 0; |
- std::string result; |
- |
- switch (variable) { |
- case NPNURLVProxy: { |
- result = "DIRECT"; |
- if (!webkit_glue::FindProxyForUrl(GURL((std::string(url))), &result)) |
- return NPERR_GENERIC_ERROR; |
- |
- break; |
- } |
- case NPNURLVCookie: { |
- scoped_refptr<NPAPI::PluginInstance> plugin(FindInstance(id)); |
- if (!plugin) |
- return NPERR_GENERIC_ERROR; |
- |
- webkit_glue::WebPlugin* webplugin = plugin->webplugin(); |
- if (!webplugin) |
- return NPERR_GENERIC_ERROR; |
- |
- // Bypass third-party cookie blocking by using the url as the |
- // first_party_for_cookies. |
- GURL cookies_url((std::string(url))); |
- result = webplugin->GetCookies(cookies_url, cookies_url); |
- break; |
- } |
- default: |
- return NPERR_GENERIC_ERROR; |
- } |
- |
- // Allocate this using the NPAPI allocator. The plugin will call |
- // NPN_Free to free this. |
- *value = static_cast<char*>(NPN_MemAlloc(result.length() + 1)); |
- base::strlcpy(*value, result.c_str(), result.length() + 1); |
- *len = result.length(); |
- |
- return NPERR_NO_ERROR; |
-} |
- |
-NPError NPN_SetValueForURL(NPP id, |
- NPNURLVariable variable, |
- const char* url, |
- const char* value, |
- uint32_t len) { |
- if (!id) |
- return NPERR_INVALID_PARAM; |
- |
- if (!url || !*url) |
- return NPERR_INVALID_URL; |
- |
- switch (variable) { |
- case NPNURLVCookie: { |
- scoped_refptr<NPAPI::PluginInstance> plugin(FindInstance(id)); |
- if (!plugin) |
- return NPERR_GENERIC_ERROR; |
- |
- webkit_glue::WebPlugin* webplugin = plugin->webplugin(); |
- if (!webplugin) |
- return NPERR_GENERIC_ERROR; |
- |
- std::string cookie(value, len); |
- GURL cookies_url((std::string(url))); |
- webplugin->SetCookie(cookies_url, cookies_url, cookie); |
- return NPERR_NO_ERROR; |
- } |
- case NPNURLVProxy: |
- // We don't support setting proxy values, fall through... |
- break; |
- default: |
- // Fall through and return an error... |
- break; |
- } |
- |
- return NPERR_GENERIC_ERROR; |
-} |
- |
-NPError NPN_GetAuthenticationInfo(NPP id, |
- const char* protocol, |
- const char* host, |
- int32_t port, |
- const char* scheme, |
- const char* realm, |
- char** username, |
- uint32_t* ulen, |
- char** password, |
- uint32_t* plen) { |
- if (!id || !protocol || !host || !scheme || !realm || !username || |
- !ulen || !password || !plen) |
- return NPERR_INVALID_PARAM; |
- |
- // TODO: implement me (bug 23928) |
- return NPERR_GENERIC_ERROR; |
-} |
- |
-uint32_t NPN_ScheduleTimer(NPP id, |
- uint32_t interval, |
- NPBool repeat, |
- void (*func)(NPP id, uint32_t timer_id)) { |
- scoped_refptr<NPAPI::PluginInstance> plugin(FindInstance(id)); |
- if (!plugin) |
- return 0; |
- |
- return plugin->ScheduleTimer(interval, repeat, func); |
-} |
- |
-void NPN_UnscheduleTimer(NPP id, uint32_t timer_id) { |
- scoped_refptr<NPAPI::PluginInstance> plugin(FindInstance(id)); |
- if (plugin) |
- plugin->UnscheduleTimer(timer_id); |
-} |
- |
-NPError NPN_PopUpContextMenu(NPP id, NPMenu* menu) { |
- if (!menu) |
- return NPERR_INVALID_PARAM; |
- |
- scoped_refptr<NPAPI::PluginInstance> plugin(FindInstance(id)); |
- if (plugin.get()) { |
- return plugin->PopUpContextMenu(menu); |
- } |
- NOTREACHED(); |
- return NPERR_GENERIC_ERROR; |
-} |
- |
-NPBool NPN_ConvertPoint(NPP id, double sourceX, double sourceY, |
- NPCoordinateSpace sourceSpace, |
- double *destX, double *destY, |
- NPCoordinateSpace destSpace) { |
- scoped_refptr<NPAPI::PluginInstance> plugin(FindInstance(id)); |
- if (plugin.get()) { |
- return plugin->ConvertPoint(sourceX, sourceY, sourceSpace, |
- destX, destY, destSpace); |
- } |
- NOTREACHED(); |
- return false; |
-} |
- |
-NPBool NPN_HandleEvent(NPP id, void *event, NPBool handled) { |
- // TODO: Implement advanced key handling: http://crbug.com/46578 |
- NOTIMPLEMENTED(); |
- return false; |
-} |
- |
-NPBool NPN_UnfocusInstance(NPP id, NPFocusDirection direction) { |
- // TODO: Implement advanced key handling: http://crbug.com/46578 |
- NOTIMPLEMENTED(); |
- return false; |
-} |
- |
-void NPN_URLRedirectResponse(NPP instance, void* notify_data, NPBool allow) { |
- scoped_refptr<NPAPI::PluginInstance> plugin(FindInstance(instance)); |
- if (plugin.get()) { |
- plugin->URLRedirectResponse(!!allow, notify_data); |
- } |
-} |
- |
-} // extern "C" |