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