| 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 "webkit/plugins/npapi/plugin_host.h" | |
| 6 | |
| 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 "net/base/net_util.h" | |
| 17 #include "third_party/WebKit/public/web/WebBindings.h" | |
| 18 #include "third_party/WebKit/public/web/WebKit.h" | |
| 19 #include "third_party/npapi/bindings/npruntime.h" | |
| 20 #include "ui/base/ui_base_switches.h" | |
| 21 #include "ui/gl/gl_implementation.h" | |
| 22 #include "ui/gl/gl_surface.h" | |
| 23 #include "webkit/common/user_agent/user_agent.h" | |
| 24 #include "webkit/plugins/npapi/plugin_instance.h" | |
| 25 #include "webkit/plugins/npapi/plugin_lib.h" | |
| 26 #include "webkit/plugins/npapi/plugin_stream_url.h" | |
| 27 #include "webkit/plugins/npapi/webplugin_delegate.h" | |
| 28 #include "webkit/plugins/webplugininfo.h" | |
| 29 | |
| 30 #if defined(OS_MACOSX) | |
| 31 #include "base/mac/mac_util.h" | |
| 32 #endif | |
| 33 | |
| 34 using WebKit::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 webkit { | |
| 44 namespace npapi { | |
| 45 | |
| 46 // Finds a PluginInstance from an NPP. | |
| 47 // The caller must take a reference if needed. | |
| 48 static PluginInstance* FindInstance(NPP id) { | |
| 49 if (id == NULL) { | |
| 50 return NULL; | |
| 51 } | |
| 52 return reinterpret_cast<PluginInstance*>(id->ndata); | |
| 53 } | |
| 54 | |
| 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)) | |
| 62 return false; | |
| 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. | |
| 66 gfx::GLImplementation implementation = gfx::GetGLImplementation(); | |
| 67 if (implementation == gfx::kGLImplementationNone) { | |
| 68 // Not initialized yet. | |
| 69 if (!gfx::GLSurface::InitializeOneOff()) { | |
| 70 return false; | |
| 71 } | |
| 72 implementation = gfx::GetGLImplementation(); | |
| 73 } | |
| 74 return (implementation == gfx::kGLImplementationDesktopGL); | |
| 75 } | |
| 76 #endif | |
| 77 | |
| 78 PluginHost::PluginHost() { | |
| 79 InitializeHostFuncs(); | |
| 80 } | |
| 81 | |
| 82 PluginHost::~PluginHost() { | |
| 83 } | |
| 84 | |
| 85 PluginHost *PluginHost::Singleton() { | |
| 86 CR_DEFINE_STATIC_LOCAL(scoped_refptr<PluginHost>, singleton, ()); | |
| 87 if (singleton.get() == NULL) { | |
| 88 singleton = new PluginHost(); | |
| 89 } | |
| 90 | |
| 91 DCHECK(singleton.get() != NULL); | |
| 92 return singleton.get(); | |
| 93 } | |
| 94 | |
| 95 void PluginHost::InitializeHostFuncs() { | |
| 96 memset(&host_funcs_, 0, sizeof(host_funcs_)); | |
| 97 host_funcs_.size = sizeof(host_funcs_); | |
| 98 host_funcs_.version = (NP_VERSION_MAJOR << 8) | (NP_VERSION_MINOR); | |
| 99 | |
| 100 // The "basic" functions | |
| 101 host_funcs_.geturl = &NPN_GetURL; | |
| 102 host_funcs_.posturl = &NPN_PostURL; | |
| 103 host_funcs_.requestread = &NPN_RequestRead; | |
| 104 host_funcs_.newstream = &NPN_NewStream; | |
| 105 host_funcs_.write = &NPN_Write; | |
| 106 host_funcs_.destroystream = &NPN_DestroyStream; | |
| 107 host_funcs_.status = &NPN_Status; | |
| 108 host_funcs_.uagent = &NPN_UserAgent; | |
| 109 host_funcs_.memalloc = &NPN_MemAlloc; | |
| 110 host_funcs_.memfree = &NPN_MemFree; | |
| 111 host_funcs_.memflush = &NPN_MemFlush; | |
| 112 host_funcs_.reloadplugins = &NPN_ReloadPlugins; | |
| 113 | |
| 114 // Stubs for deprecated Java functions | |
| 115 host_funcs_.getJavaEnv = &NPN_GetJavaEnv; | |
| 116 host_funcs_.getJavaPeer = &NPN_GetJavaPeer; | |
| 117 | |
| 118 // Advanced functions we implement | |
| 119 host_funcs_.geturlnotify = &NPN_GetURLNotify; | |
| 120 host_funcs_.posturlnotify = &NPN_PostURLNotify; | |
| 121 host_funcs_.getvalue = &NPN_GetValue; | |
| 122 host_funcs_.setvalue = &NPN_SetValue; | |
| 123 host_funcs_.invalidaterect = &NPN_InvalidateRect; | |
| 124 host_funcs_.invalidateregion = &NPN_InvalidateRegion; | |
| 125 host_funcs_.forceredraw = &NPN_ForceRedraw; | |
| 126 | |
| 127 // These come from the Javascript Engine | |
| 128 host_funcs_.getstringidentifier = WebBindings::getStringIdentifier; | |
| 129 host_funcs_.getstringidentifiers = WebBindings::getStringIdentifiers; | |
| 130 host_funcs_.getintidentifier = WebBindings::getIntIdentifier; | |
| 131 host_funcs_.identifierisstring = WebBindings::identifierIsString; | |
| 132 host_funcs_.utf8fromidentifier = WebBindings::utf8FromIdentifier; | |
| 133 host_funcs_.intfromidentifier = WebBindings::intFromIdentifier; | |
| 134 host_funcs_.createobject = WebBindings::createObject; | |
| 135 host_funcs_.retainobject = WebBindings::retainObject; | |
| 136 host_funcs_.releaseobject = WebBindings::releaseObject; | |
| 137 host_funcs_.invoke = WebBindings::invoke; | |
| 138 host_funcs_.invokeDefault = WebBindings::invokeDefault; | |
| 139 host_funcs_.evaluate = WebBindings::evaluate; | |
| 140 host_funcs_.getproperty = WebBindings::getProperty; | |
| 141 host_funcs_.setproperty = WebBindings::setProperty; | |
| 142 host_funcs_.removeproperty = WebBindings::removeProperty; | |
| 143 host_funcs_.hasproperty = WebBindings::hasProperty; | |
| 144 host_funcs_.hasmethod = WebBindings::hasMethod; | |
| 145 host_funcs_.releasevariantvalue = WebBindings::releaseVariantValue; | |
| 146 host_funcs_.setexception = WebBindings::setException; | |
| 147 host_funcs_.pushpopupsenabledstate = NPN_PushPopupsEnabledState; | |
| 148 host_funcs_.poppopupsenabledstate = NPN_PopPopupsEnabledState; | |
| 149 host_funcs_.enumerate = WebBindings::enumerate; | |
| 150 host_funcs_.pluginthreadasynccall = NPN_PluginThreadAsyncCall; | |
| 151 host_funcs_.construct = WebBindings::construct; | |
| 152 host_funcs_.getvalueforurl = NPN_GetValueForURL; | |
| 153 host_funcs_.setvalueforurl = NPN_SetValueForURL; | |
| 154 host_funcs_.getauthenticationinfo = NPN_GetAuthenticationInfo; | |
| 155 host_funcs_.scheduletimer = NPN_ScheduleTimer; | |
| 156 host_funcs_.unscheduletimer = NPN_UnscheduleTimer; | |
| 157 host_funcs_.popupcontextmenu = NPN_PopUpContextMenu; | |
| 158 host_funcs_.convertpoint = NPN_ConvertPoint; | |
| 159 host_funcs_.handleevent = NPN_HandleEvent; | |
| 160 host_funcs_.unfocusinstance = NPN_UnfocusInstance; | |
| 161 host_funcs_.urlredirectresponse = NPN_URLRedirectResponse; | |
| 162 } | |
| 163 | |
| 164 void PluginHost::PatchNPNetscapeFuncs(NPNetscapeFuncs* overrides) { | |
| 165 // When running in the plugin process, we need to patch the NPN functions | |
| 166 // that the plugin calls to interact with NPObjects that we give. Otherwise | |
| 167 // the plugin will call the v8 NPN functions, which won't work since we have | |
| 168 // an NPObjectProxy and not a real v8 implementation. | |
| 169 if (overrides->invoke) | |
| 170 host_funcs_.invoke = overrides->invoke; | |
| 171 | |
| 172 if (overrides->invokeDefault) | |
| 173 host_funcs_.invokeDefault = overrides->invokeDefault; | |
| 174 | |
| 175 if (overrides->evaluate) | |
| 176 host_funcs_.evaluate = overrides->evaluate; | |
| 177 | |
| 178 if (overrides->getproperty) | |
| 179 host_funcs_.getproperty = overrides->getproperty; | |
| 180 | |
| 181 if (overrides->setproperty) | |
| 182 host_funcs_.setproperty = overrides->setproperty; | |
| 183 | |
| 184 if (overrides->removeproperty) | |
| 185 host_funcs_.removeproperty = overrides->removeproperty; | |
| 186 | |
| 187 if (overrides->hasproperty) | |
| 188 host_funcs_.hasproperty = overrides->hasproperty; | |
| 189 | |
| 190 if (overrides->hasmethod) | |
| 191 host_funcs_.hasmethod = overrides->hasmethod; | |
| 192 | |
| 193 if (overrides->setexception) | |
| 194 host_funcs_.setexception = overrides->setexception; | |
| 195 | |
| 196 if (overrides->enumerate) | |
| 197 host_funcs_.enumerate = overrides->enumerate; | |
| 198 } | |
| 199 | |
| 200 bool PluginHost::SetPostData(const char* buf, | |
| 201 uint32 length, | |
| 202 std::vector<std::string>* names, | |
| 203 std::vector<std::string>* values, | |
| 204 std::vector<char>* body) { | |
| 205 // Use a state table to do the parsing. Whitespace must be | |
| 206 // trimmed after the fact if desired. In our case, we actually | |
| 207 // don't care about the whitespace, because we're just going to | |
| 208 // pass this back into another POST. This function strips out the | |
| 209 // "Content-length" header and does not append it to the request. | |
| 210 | |
| 211 // | |
| 212 // This parser takes action only on state changes. | |
| 213 // | |
| 214 // Transition table: | |
| 215 // : \n NULL Other | |
| 216 // 0 GetHeader 1 2 4 0 | |
| 217 // 1 GetValue 1 0 3 1 | |
| 218 // 2 GetData 2 2 3 2 | |
| 219 // 3 DONE | |
| 220 // 4 ERR | |
| 221 // | |
| 222 enum { INPUT_COLON=0, INPUT_NEWLINE, INPUT_NULL, INPUT_OTHER }; | |
| 223 enum { GETNAME, GETVALUE, GETDATA, DONE, ERR }; | |
| 224 int statemachine[3][4] = { { GETVALUE, GETDATA, GETDATA, GETNAME }, | |
| 225 { GETVALUE, GETNAME, DONE, GETVALUE }, | |
| 226 { GETDATA, GETDATA, DONE, GETDATA } }; | |
| 227 std::string name, value; | |
| 228 const char* ptr = static_cast<const char*>(buf); | |
| 229 const char* start = ptr; | |
| 230 int state = GETNAME; // initial state | |
| 231 bool done = false; | |
| 232 bool err = false; | |
| 233 do { | |
| 234 int input; | |
| 235 | |
| 236 // Translate the current character into an input | |
| 237 // for the state table. | |
| 238 switch (*ptr) { | |
| 239 case ':' : | |
| 240 input = INPUT_COLON; | |
| 241 break; | |
| 242 case '\n': | |
| 243 input = INPUT_NEWLINE; | |
| 244 break; | |
| 245 case 0 : | |
| 246 input = INPUT_NULL; | |
| 247 break; | |
| 248 default : | |
| 249 input = INPUT_OTHER; | |
| 250 break; | |
| 251 } | |
| 252 | |
| 253 int newstate = statemachine[state][input]; | |
| 254 | |
| 255 // Take action based on the new state. | |
| 256 if (state != newstate) { | |
| 257 switch (newstate) { | |
| 258 case GETNAME: | |
| 259 // Got a value. | |
| 260 value = std::string(start, ptr - start); | |
| 261 TrimWhitespace(value, TRIM_ALL, &value); | |
| 262 // If the name field is empty, we'll skip this header | |
| 263 // but we won't error out. | |
| 264 if (!name.empty() && name != "content-length") { | |
| 265 names->push_back(name); | |
| 266 values->push_back(value); | |
| 267 } | |
| 268 start = ptr + 1; | |
| 269 break; | |
| 270 case GETVALUE: | |
| 271 // Got a header. | |
| 272 name = StringToLowerASCII(std::string(start, ptr - start)); | |
| 273 TrimWhitespace(name, TRIM_ALL, &name); | |
| 274 start = ptr + 1; | |
| 275 break; | |
| 276 case GETDATA: { | |
| 277 // Finished headers, now get body | |
| 278 if (*ptr) | |
| 279 start = ptr + 1; | |
| 280 size_t previous_size = body->size(); | |
| 281 size_t new_body_size = length - static_cast<int>(start - buf); | |
| 282 body->resize(previous_size + new_body_size); | |
| 283 if (!body->empty()) | |
| 284 memcpy(&body->front() + previous_size, start, new_body_size); | |
| 285 done = true; | |
| 286 break; | |
| 287 } | |
| 288 case ERR: | |
| 289 // error | |
| 290 err = true; | |
| 291 done = true; | |
| 292 break; | |
| 293 } | |
| 294 } | |
| 295 state = newstate; | |
| 296 ptr++; | |
| 297 } while (!done); | |
| 298 | |
| 299 return !err; | |
| 300 } | |
| 301 | |
| 302 } // namespace npapi | |
| 303 } // namespace webkit | |
| 304 | |
| 305 extern "C" { | |
| 306 | |
| 307 using webkit::npapi::FindInstance; | |
| 308 using webkit::npapi::PluginHost; | |
| 309 using webkit::npapi::PluginInstance; | |
| 310 using webkit::npapi::WebPlugin; | |
| 311 | |
| 312 // Allocates memory from the host's memory space. | |
| 313 void* NPN_MemAlloc(uint32_t size) { | |
| 314 // Note: We must use the same allocator/deallocator | |
| 315 // that is used by the javascript library, as some of the | |
| 316 // JS APIs will pass memory to the plugin which the plugin | |
| 317 // will attempt to free. | |
| 318 return malloc(size); | |
| 319 } | |
| 320 | |
| 321 // Deallocates memory from the host's memory space | |
| 322 void NPN_MemFree(void* ptr) { | |
| 323 if (ptr != NULL && ptr != reinterpret_cast<void*>(-1)) | |
| 324 free(ptr); | |
| 325 } | |
| 326 | |
| 327 // Requests that the host free a specified amount of memory. | |
| 328 uint32_t NPN_MemFlush(uint32_t size) { | |
| 329 // This is not relevant on Windows; MAC specific | |
| 330 return size; | |
| 331 } | |
| 332 | |
| 333 // This is for dynamic discovery of new plugins. | |
| 334 // Should force a re-scan of the plugins directory to load new ones. | |
| 335 void NPN_ReloadPlugins(NPBool reload_pages) { | |
| 336 WebKit::resetPluginCache(reload_pages ? true : false); | |
| 337 } | |
| 338 | |
| 339 // Requests a range of bytes for a seekable stream. | |
| 340 NPError NPN_RequestRead(NPStream* stream, NPByteRange* range_list) { | |
| 341 if (!stream || !range_list) | |
| 342 return NPERR_GENERIC_ERROR; | |
| 343 | |
| 344 scoped_refptr<PluginInstance> plugin( | |
| 345 reinterpret_cast<PluginInstance*>(stream->ndata)); | |
| 346 if (!plugin.get()) | |
| 347 return NPERR_GENERIC_ERROR; | |
| 348 | |
| 349 plugin->RequestRead(stream, range_list); | |
| 350 return NPERR_NO_ERROR; | |
| 351 } | |
| 352 | |
| 353 // Generic form of GetURL for common code between GetURL and GetURLNotify. | |
| 354 static NPError GetURLNotify(NPP id, | |
| 355 const char* url, | |
| 356 const char* target, | |
| 357 bool notify, | |
| 358 void* notify_data) { | |
| 359 if (!url) | |
| 360 return NPERR_INVALID_URL; | |
| 361 | |
| 362 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
| 363 if (!plugin.get()) { | |
| 364 return NPERR_GENERIC_ERROR; | |
| 365 } | |
| 366 | |
| 367 plugin->RequestURL(url, "GET", target, NULL, 0, notify, notify_data); | |
| 368 return NPERR_NO_ERROR; | |
| 369 } | |
| 370 | |
| 371 // Requests creation of a new stream with the contents of the | |
| 372 // specified URL; gets notification of the result. | |
| 373 NPError NPN_GetURLNotify(NPP id, | |
| 374 const char* url, | |
| 375 const char* target, | |
| 376 void* notify_data) { | |
| 377 // This is identical to NPN_GetURL, but after finishing, the | |
| 378 // browser will call NPP_URLNotify to inform the plugin that | |
| 379 // it has completed. | |
| 380 | |
| 381 // According to the NPAPI documentation, if target == _self | |
| 382 // or a parent to _self, the browser should return NPERR_INVALID_PARAM, | |
| 383 // because it can't notify the plugin once deleted. This is | |
| 384 // absolutely false; firefox doesn't do this, and Flash relies on | |
| 385 // being able to use this. | |
| 386 | |
| 387 // Also according to the NPAPI documentation, we should return | |
| 388 // NPERR_INVALID_URL if the url requested is not valid. However, | |
| 389 // this would require that we synchronously start fetching the | |
| 390 // URL. That just isn't practical. As such, there really is | |
| 391 // no way to return this error. From looking at the Firefox | |
| 392 // implementation, it doesn't look like Firefox does this either. | |
| 393 | |
| 394 return GetURLNotify(id, url, target, true, notify_data); | |
| 395 } | |
| 396 | |
| 397 NPError NPN_GetURL(NPP id, const char* url, const char* target) { | |
| 398 // Notes: | |
| 399 // Request from the Plugin to fetch content either for the plugin | |
| 400 // or to be placed into a browser window. | |
| 401 // | |
| 402 // If target == null, the browser fetches content and streams to plugin. | |
| 403 // otherwise, the browser loads content into an existing browser frame. | |
| 404 // If the target is the window/frame containing the plugin, the plugin | |
| 405 // may be destroyed. | |
| 406 // If the target is _blank, a mailto: or news: url open content in a new | |
| 407 // browser window | |
| 408 // If the target is _self, no other instance of the plugin is created. The | |
| 409 // plugin continues to operate in its own window | |
| 410 | |
| 411 return GetURLNotify(id, url, target, false, 0); | |
| 412 } | |
| 413 | |
| 414 // Generic form of PostURL for common code between PostURL and PostURLNotify. | |
| 415 static NPError PostURLNotify(NPP id, | |
| 416 const char* url, | |
| 417 const char* target, | |
| 418 uint32_t len, | |
| 419 const char* buf, | |
| 420 NPBool file, | |
| 421 bool notify, | |
| 422 void* notify_data) { | |
| 423 if (!url) | |
| 424 return NPERR_INVALID_URL; | |
| 425 | |
| 426 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
| 427 if (!plugin.get()) { | |
| 428 NOTREACHED(); | |
| 429 return NPERR_GENERIC_ERROR; | |
| 430 } | |
| 431 | |
| 432 std::string post_file_contents; | |
| 433 | |
| 434 if (file) { | |
| 435 // Post data to be uploaded from a file. This can be handled in two | |
| 436 // ways. | |
| 437 // 1. Read entire file and send the contents as if it was a post data | |
| 438 // specified in the argument | |
| 439 // 2. Send just the file details and read them in the browser at the | |
| 440 // time of sending the request. | |
| 441 // Approach 2 is more efficient but complicated. Approach 1 has a major | |
| 442 // drawback of sending potentially large data over two IPC hops. In a way | |
| 443 // 'large data over IPC' problem exists as it is in case of plugin giving | |
| 444 // the data directly instead of in a file. | |
| 445 // Currently we are going with the approach 1 to get the feature working. | |
| 446 // We can optimize this later with approach 2. | |
| 447 | |
| 448 // TODO(joshia): Design a scheme to send a file descriptor instead of | |
| 449 // entire file contents across. | |
| 450 | |
| 451 // Security alert: | |
| 452 // --------------- | |
| 453 // Here we are blindly uploading whatever file requested by a plugin. | |
| 454 // This is risky as someone could exploit a plugin to send private | |
| 455 // data in arbitrary locations. | |
| 456 // A malicious (non-sandboxed) plugin has unfeterred access to OS | |
| 457 // resources and can do this anyway without using browser's HTTP stack. | |
| 458 // FWIW, Firefox and Safari don't perform any security checks. | |
| 459 | |
| 460 if (!buf) | |
| 461 return NPERR_FILE_NOT_FOUND; | |
| 462 | |
| 463 std::string file_path_ascii(buf); | |
| 464 base::FilePath file_path; | |
| 465 static const char kFileUrlPrefix[] = "file:"; | |
| 466 if (StartsWithASCII(file_path_ascii, kFileUrlPrefix, false)) { | |
| 467 GURL file_url(file_path_ascii); | |
| 468 DCHECK(file_url.SchemeIsFile()); | |
| 469 net::FileURLToFilePath(file_url, &file_path); | |
| 470 } else { | |
| 471 file_path = base::FilePath::FromWStringHack( | |
| 472 base::SysNativeMBToWide(file_path_ascii)); | |
| 473 } | |
| 474 | |
| 475 base::PlatformFileInfo post_file_info; | |
| 476 if (!file_util::GetFileInfo(file_path, &post_file_info) || | |
| 477 post_file_info.is_directory) | |
| 478 return NPERR_FILE_NOT_FOUND; | |
| 479 | |
| 480 if (!file_util::ReadFileToString(file_path, &post_file_contents)) | |
| 481 return NPERR_FILE_NOT_FOUND; | |
| 482 | |
| 483 buf = post_file_contents.c_str(); | |
| 484 len = post_file_contents.size(); | |
| 485 } | |
| 486 | |
| 487 // The post data sent by a plugin contains both headers | |
| 488 // and post data. Example: | |
| 489 // Content-type: text/html | |
| 490 // Content-length: 200 | |
| 491 // | |
| 492 // <200 bytes of content here> | |
| 493 // | |
| 494 // Unfortunately, our stream needs these broken apart, | |
| 495 // so we need to parse the data and set headers and data | |
| 496 // separately. | |
| 497 plugin->RequestURL(url, "POST", target, buf, len, notify, notify_data); | |
| 498 return NPERR_NO_ERROR; | |
| 499 } | |
| 500 | |
| 501 NPError NPN_PostURLNotify(NPP id, | |
| 502 const char* url, | |
| 503 const char* target, | |
| 504 uint32_t len, | |
| 505 const char* buf, | |
| 506 NPBool file, | |
| 507 void* notify_data) { | |
| 508 return PostURLNotify(id, url, target, len, buf, file, true, notify_data); | |
| 509 } | |
| 510 | |
| 511 NPError NPN_PostURL(NPP id, | |
| 512 const char* url, | |
| 513 const char* target, | |
| 514 uint32_t len, | |
| 515 const char* buf, | |
| 516 NPBool file) { | |
| 517 // POSTs data to an URL, either from a temp file or a buffer. | |
| 518 // If file is true, buf contains a temp file (which host will delete after | |
| 519 // completing), and len contains the length of the filename. | |
| 520 // If file is false, buf contains the data to send, and len contains the | |
| 521 // length of the buffer | |
| 522 // | |
| 523 // If target is null, | |
| 524 // server response is returned to the plugin | |
| 525 // If target is _current, _self, or _top, | |
| 526 // server response is written to the plugin window and plugin is unloaded. | |
| 527 // If target is _new or _blank, | |
| 528 // server response is written to a new browser window | |
| 529 // If target is an existing frame, | |
| 530 // server response goes to that frame. | |
| 531 // | |
| 532 // For protocols other than FTP | |
| 533 // file uploads must be line-end converted from \r\n to \n | |
| 534 // | |
| 535 // Note: you cannot specify headers (even a blank line) in a memory buffer, | |
| 536 // use NPN_PostURLNotify | |
| 537 | |
| 538 return PostURLNotify(id, url, target, len, buf, file, false, 0); | |
| 539 } | |
| 540 | |
| 541 NPError NPN_NewStream(NPP id, | |
| 542 NPMIMEType type, | |
| 543 const char* target, | |
| 544 NPStream** stream) { | |
| 545 // Requests creation of a new data stream produced by the plugin, | |
| 546 // consumed by the browser. | |
| 547 // | |
| 548 // Browser should put this stream into a window target. | |
| 549 // | |
| 550 // TODO: implement me | |
| 551 DVLOG(1) << "NPN_NewStream is not implemented yet."; | |
| 552 return NPERR_GENERIC_ERROR; | |
| 553 } | |
| 554 | |
| 555 int32_t NPN_Write(NPP id, NPStream* stream, int32_t len, void* buffer) { | |
| 556 // Writes data to an existing Plugin-created stream. | |
| 557 | |
| 558 // TODO: implement me | |
| 559 DVLOG(1) << "NPN_Write is not implemented yet."; | |
| 560 return NPERR_GENERIC_ERROR; | |
| 561 } | |
| 562 | |
| 563 NPError NPN_DestroyStream(NPP id, NPStream* stream, NPReason reason) { | |
| 564 // Destroys a stream (could be created by plugin or browser). | |
| 565 // | |
| 566 // Reasons: | |
| 567 // NPRES_DONE - normal completion | |
| 568 // NPRES_USER_BREAK - user terminated | |
| 569 // NPRES_NETWORK_ERROR - network error (all errors fit here?) | |
| 570 // | |
| 571 // | |
| 572 | |
| 573 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
| 574 if (plugin.get() == NULL) { | |
| 575 NOTREACHED(); | |
| 576 return NPERR_GENERIC_ERROR; | |
| 577 } | |
| 578 | |
| 579 return plugin->NPP_DestroyStream(stream, reason); | |
| 580 } | |
| 581 | |
| 582 const char* NPN_UserAgent(NPP id) { | |
| 583 #if defined(OS_WIN) | |
| 584 // Flash passes in a null id during the NP_initialize call. We need to | |
| 585 // default to the Mozilla user agent if we don't have an NPP instance or | |
| 586 // else Flash won't request windowless mode. | |
| 587 bool use_mozilla_user_agent = true; | |
| 588 if (id) { | |
| 589 scoped_refptr<PluginInstance> plugin = FindInstance(id); | |
| 590 if (plugin.get() && !plugin->use_mozilla_user_agent()) | |
| 591 use_mozilla_user_agent = false; | |
| 592 } | |
| 593 | |
| 594 if (use_mozilla_user_agent) | |
| 595 return "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9a1) " | |
| 596 "Gecko/20061103 Firefox/2.0a1"; | |
| 597 #endif | |
| 598 | |
| 599 return webkit_glue::GetUserAgent(GURL()).c_str(); | |
| 600 } | |
| 601 | |
| 602 void NPN_Status(NPP id, const char* message) { | |
| 603 // Displays a message on the status line of the browser window. | |
| 604 | |
| 605 // TODO: implement me | |
| 606 DVLOG(1) << "NPN_Status is not implemented yet."; | |
| 607 } | |
| 608 | |
| 609 void NPN_InvalidateRect(NPP id, NPRect *invalidRect) { | |
| 610 // Invalidates specified drawing area prior to repainting or refreshing a | |
| 611 // windowless plugin | |
| 612 | |
| 613 // Before a windowless plugin can refresh part of its drawing area, it must | |
| 614 // first invalidate it. This function causes the NPP_HandleEvent method to | |
| 615 // pass an update event or a paint message to the plug-in. After calling | |
| 616 // this method, the plug-in recieves a paint message asynchronously. | |
| 617 | |
| 618 // The browser redraws invalid areas of the document and any windowless | |
| 619 // plug-ins at regularly timed intervals. To force a paint message, the | |
| 620 // plug-in can call NPN_ForceRedraw after calling this method. | |
| 621 | |
| 622 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
| 623 if (plugin.get() && plugin->webplugin()) { | |
| 624 if (invalidRect) { | |
| 625 #if defined(OS_WIN) | |
| 626 if (!plugin->windowless()) { | |
| 627 RECT rect = {0}; | |
| 628 rect.left = invalidRect->left; | |
| 629 rect.right = invalidRect->right; | |
| 630 rect.top = invalidRect->top; | |
| 631 rect.bottom = invalidRect->bottom; | |
| 632 ::InvalidateRect(plugin->window_handle(), &rect, false); | |
| 633 return; | |
| 634 } | |
| 635 #endif | |
| 636 gfx::Rect rect(invalidRect->left, | |
| 637 invalidRect->top, | |
| 638 invalidRect->right - invalidRect->left, | |
| 639 invalidRect->bottom - invalidRect->top); | |
| 640 plugin->webplugin()->InvalidateRect(rect); | |
| 641 } else { | |
| 642 plugin->webplugin()->Invalidate(); | |
| 643 } | |
| 644 } | |
| 645 } | |
| 646 | |
| 647 void NPN_InvalidateRegion(NPP id, NPRegion invalidRegion) { | |
| 648 // Invalidates a specified drawing region prior to repainting | |
| 649 // or refreshing a window-less plugin. | |
| 650 // | |
| 651 // Similar to NPN_InvalidateRect. | |
| 652 | |
| 653 // TODO: this is overkill--add platform-specific region handling (at the | |
| 654 // very least, fetch the region's bounding box and pass it to InvalidateRect). | |
| 655 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
| 656 DCHECK(plugin.get() != NULL); | |
| 657 if (plugin.get() && plugin->webplugin()) | |
| 658 plugin->webplugin()->Invalidate(); | |
| 659 } | |
| 660 | |
| 661 void NPN_ForceRedraw(NPP id) { | |
| 662 // Forces repaint for a windowless plug-in. | |
| 663 // | |
| 664 // We deliberately do not implement this; we don't want plugins forcing | |
| 665 // synchronous paints. | |
| 666 } | |
| 667 | |
| 668 NPError NPN_GetValue(NPP id, NPNVariable variable, void* value) { | |
| 669 // Allows the plugin to query the browser for information | |
| 670 // | |
| 671 // Variables: | |
| 672 // NPNVxDisplay (unix only) | |
| 673 // NPNVxtAppContext (unix only) | |
| 674 // NPNVnetscapeWindow (win only) - Gets the native window on which the | |
| 675 // plug-in drawing occurs, returns HWND | |
| 676 // NPNVjavascriptEnabledBool: tells whether Javascript is enabled | |
| 677 // NPNVasdEnabledBool: tells whether SmartUpdate is enabled | |
| 678 // NPNVOfflineBool: tells whether offline-mode is enabled | |
| 679 | |
| 680 NPError rv = NPERR_GENERIC_ERROR; | |
| 681 | |
| 682 switch (static_cast<int>(variable)) { | |
| 683 case NPNVWindowNPObject: { | |
| 684 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
| 685 if (!plugin.get()) { | |
| 686 NOTREACHED(); | |
| 687 return NPERR_INVALID_INSTANCE_ERROR; | |
| 688 } | |
| 689 NPObject *np_object = plugin->webplugin()->GetWindowScriptNPObject(); | |
| 690 // Return value is expected to be retained, as | |
| 691 // described here: | |
| 692 // <http://www.mozilla.org/projects/plugins/npruntime.html#browseraccess> | |
| 693 if (np_object) { | |
| 694 WebBindings::retainObject(np_object); | |
| 695 void **v = (void **)value; | |
| 696 *v = np_object; | |
| 697 rv = NPERR_NO_ERROR; | |
| 698 } else { | |
| 699 NOTREACHED(); | |
| 700 } | |
| 701 break; | |
| 702 } | |
| 703 case NPNVPluginElementNPObject: { | |
| 704 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
| 705 if (!plugin.get()) { | |
| 706 NOTREACHED(); | |
| 707 return NPERR_INVALID_INSTANCE_ERROR; | |
| 708 } | |
| 709 NPObject *np_object = plugin->webplugin()->GetPluginElement(); | |
| 710 // Return value is expected to be retained, as | |
| 711 // described here: | |
| 712 // <http://www.mozilla.org/projects/plugins/npruntime.html#browseraccess> | |
| 713 if (np_object) { | |
| 714 WebBindings::retainObject(np_object); | |
| 715 void** v = static_cast<void**>(value); | |
| 716 *v = np_object; | |
| 717 rv = NPERR_NO_ERROR; | |
| 718 } else { | |
| 719 NOTREACHED(); | |
| 720 } | |
| 721 break; | |
| 722 } | |
| 723 #if !defined(OS_MACOSX) // OS X doesn't have windowed plugins. | |
| 724 case NPNVnetscapeWindow: { | |
| 725 scoped_refptr<PluginInstance> plugin = FindInstance(id); | |
| 726 if (!plugin.get()) { | |
| 727 NOTREACHED(); | |
| 728 return NPERR_INVALID_INSTANCE_ERROR; | |
| 729 } | |
| 730 gfx::PluginWindowHandle handle = plugin->window_handle(); | |
| 731 *((void**)value) = (void*)handle; | |
| 732 rv = NPERR_NO_ERROR; | |
| 733 break; | |
| 734 } | |
| 735 #endif | |
| 736 case NPNVjavascriptEnabledBool: { | |
| 737 // yes, JS is enabled. | |
| 738 *((void**)value) = (void*)1; | |
| 739 rv = NPERR_NO_ERROR; | |
| 740 break; | |
| 741 } | |
| 742 #if defined(TOOLKIT_GTK) | |
| 743 case NPNVToolkit: | |
| 744 // Tell them we are GTK2. (The alternative is GTK 1.2.) | |
| 745 *reinterpret_cast<int*>(value) = NPNVGtk2; | |
| 746 rv = NPERR_NO_ERROR; | |
| 747 break; | |
| 748 | |
| 749 case NPNVSupportsXEmbedBool: | |
| 750 *reinterpret_cast<NPBool*>(value) = true; | |
| 751 rv = NPERR_NO_ERROR; | |
| 752 break; | |
| 753 #endif | |
| 754 case NPNVSupportsWindowless: { | |
| 755 NPBool* supports_windowless = reinterpret_cast<NPBool*>(value); | |
| 756 *supports_windowless = true; | |
| 757 rv = NPERR_NO_ERROR; | |
| 758 break; | |
| 759 } | |
| 760 case NPNVprivateModeBool: { | |
| 761 NPBool* private_mode = reinterpret_cast<NPBool*>(value); | |
| 762 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
| 763 if (!plugin.get()) { | |
| 764 NOTREACHED(); | |
| 765 return NPERR_INVALID_INSTANCE_ERROR; | |
| 766 } | |
| 767 *private_mode = plugin->webplugin()->IsOffTheRecord(); | |
| 768 rv = NPERR_NO_ERROR; | |
| 769 break; | |
| 770 } | |
| 771 #if defined(OS_MACOSX) | |
| 772 case NPNVpluginDrawingModel: { | |
| 773 // return the drawing model that was negotiated when we initialized. | |
| 774 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
| 775 if (!plugin.get()) { | |
| 776 NOTREACHED(); | |
| 777 return NPERR_INVALID_INSTANCE_ERROR; | |
| 778 } | |
| 779 *reinterpret_cast<int*>(value) = plugin->drawing_model(); | |
| 780 rv = NPERR_NO_ERROR; | |
| 781 break; | |
| 782 } | |
| 783 case NPNVsupportsCoreGraphicsBool: | |
| 784 case NPNVsupportsCocoaBool: { | |
| 785 // These drawing and event models are always supported. | |
| 786 NPBool* supports_model = reinterpret_cast<NPBool*>(value); | |
| 787 *supports_model = true; | |
| 788 rv = NPERR_NO_ERROR; | |
| 789 break; | |
| 790 } | |
| 791 case NPNVsupportsInvalidatingCoreAnimationBool: | |
| 792 case NPNVsupportsCoreAnimationBool: { | |
| 793 NPBool* supports_model = reinterpret_cast<NPBool*>(value); | |
| 794 *supports_model = webkit::npapi::SupportsCoreAnimationPlugins(); | |
| 795 rv = NPERR_NO_ERROR; | |
| 796 break; | |
| 797 } | |
| 798 #ifndef NP_NO_CARBON | |
| 799 case NPNVsupportsCarbonBool: | |
| 800 #endif | |
| 801 #ifndef NP_NO_QUICKDRAW | |
| 802 case NPNVsupportsQuickDrawBool: | |
| 803 #endif | |
| 804 case NPNVsupportsOpenGLBool: { | |
| 805 // These models are never supported. OpenGL was never widely supported, | |
| 806 // and QuickDraw and Carbon have been deprecated for quite some time. | |
| 807 NPBool* supports_model = reinterpret_cast<NPBool*>(value); | |
| 808 *supports_model = false; | |
| 809 rv = NPERR_NO_ERROR; | |
| 810 break; | |
| 811 } | |
| 812 case NPNVsupportsCompositingCoreAnimationPluginsBool: { | |
| 813 NPBool* supports_compositing = reinterpret_cast<NPBool*>(value); | |
| 814 *supports_compositing = | |
| 815 webkit::npapi::SupportsCoreAnimationPlugins(); | |
| 816 rv = NPERR_NO_ERROR; | |
| 817 break; | |
| 818 } | |
| 819 case NPNVsupportsUpdatedCocoaTextInputBool: { | |
| 820 // We support the clarifications to the Cocoa IME event spec. | |
| 821 NPBool* supports_update = reinterpret_cast<NPBool*>(value); | |
| 822 *supports_update = true; | |
| 823 rv = NPERR_NO_ERROR; | |
| 824 break; | |
| 825 } | |
| 826 #endif // OS_MACOSX | |
| 827 default: | |
| 828 DVLOG(1) << "NPN_GetValue(" << variable << ") is not implemented yet."; | |
| 829 break; | |
| 830 } | |
| 831 return rv; | |
| 832 } | |
| 833 | |
| 834 NPError NPN_SetValue(NPP id, NPPVariable variable, void* value) { | |
| 835 // Allows the plugin to set various modes | |
| 836 | |
| 837 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
| 838 if (!plugin.get()) { | |
| 839 NOTREACHED(); | |
| 840 return NPERR_INVALID_INSTANCE_ERROR; | |
| 841 } | |
| 842 switch(variable) { | |
| 843 case NPPVpluginWindowBool: { | |
| 844 // Sets windowless mode for display of the plugin | |
| 845 // Note: the documentation at | |
| 846 // http://developer.mozilla.org/en/docs/NPN_SetValue is wrong. When | |
| 847 // value is NULL, the mode is set to true. This is the same way Mozilla | |
| 848 // works. | |
| 849 plugin->set_windowless(value == 0); | |
| 850 return NPERR_NO_ERROR; | |
| 851 } | |
| 852 case NPPVpluginTransparentBool: { | |
| 853 // Sets transparent mode for display of the plugin | |
| 854 // | |
| 855 // Transparent plugins require the browser to paint the background | |
| 856 // before having the plugin paint. By default, windowless plugins | |
| 857 // are transparent. Making a windowless plugin opaque means that | |
| 858 // the plugin does not require the browser to paint the background. | |
| 859 bool mode = (value != 0); | |
| 860 plugin->set_transparent(mode); | |
| 861 return NPERR_NO_ERROR; | |
| 862 } | |
| 863 case NPPVjavascriptPushCallerBool: | |
| 864 // Specifies whether you are pushing or popping the JSContext off. | |
| 865 // the stack | |
| 866 // TODO: implement me | |
| 867 DVLOG(1) << "NPN_SetValue(NPPVJavascriptPushCallerBool) is not " | |
| 868 "implemented."; | |
| 869 return NPERR_GENERIC_ERROR; | |
| 870 case NPPVpluginKeepLibraryInMemory: | |
| 871 // Tells browser that plugin library should live longer than usual. | |
| 872 // TODO: implement me | |
| 873 DVLOG(1) << "NPN_SetValue(NPPVpluginKeepLibraryInMemory) is not " | |
| 874 "implemented."; | |
| 875 return NPERR_GENERIC_ERROR; | |
| 876 #if defined(OS_MACOSX) | |
| 877 case NPPVpluginDrawingModel: { | |
| 878 intptr_t model = reinterpret_cast<intptr_t>(value); | |
| 879 if (model == NPDrawingModelCoreGraphics || | |
| 880 ((model == NPDrawingModelInvalidatingCoreAnimation || | |
| 881 model == NPDrawingModelCoreAnimation) && | |
| 882 webkit::npapi::SupportsCoreAnimationPlugins())) { | |
| 883 plugin->set_drawing_model(static_cast<NPDrawingModel>(model)); | |
| 884 return NPERR_NO_ERROR; | |
| 885 } | |
| 886 return NPERR_GENERIC_ERROR; | |
| 887 } | |
| 888 case NPPVpluginEventModel: { | |
| 889 // Only the Cocoa event model is supported. | |
| 890 intptr_t model = reinterpret_cast<intptr_t>(value); | |
| 891 if (model == NPEventModelCocoa) { | |
| 892 plugin->set_event_model(static_cast<NPEventModel>(model)); | |
| 893 return NPERR_NO_ERROR; | |
| 894 } | |
| 895 return NPERR_GENERIC_ERROR; | |
| 896 } | |
| 897 #endif | |
| 898 default: | |
| 899 // TODO: implement me | |
| 900 DVLOG(1) << "NPN_SetValue(" << variable << ") is not implemented."; | |
| 901 break; | |
| 902 } | |
| 903 | |
| 904 NOTREACHED(); | |
| 905 return NPERR_GENERIC_ERROR; | |
| 906 } | |
| 907 | |
| 908 void* NPN_GetJavaEnv() { | |
| 909 // TODO: implement me | |
| 910 DVLOG(1) << "NPN_GetJavaEnv is not implemented."; | |
| 911 return NULL; | |
| 912 } | |
| 913 | |
| 914 void* NPN_GetJavaPeer(NPP) { | |
| 915 // TODO: implement me | |
| 916 DVLOG(1) << "NPN_GetJavaPeer is not implemented."; | |
| 917 return NULL; | |
| 918 } | |
| 919 | |
| 920 void NPN_PushPopupsEnabledState(NPP id, NPBool enabled) { | |
| 921 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
| 922 if (plugin.get()) | |
| 923 plugin->PushPopupsEnabledState(enabled ? true : false); | |
| 924 } | |
| 925 | |
| 926 void NPN_PopPopupsEnabledState(NPP id) { | |
| 927 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
| 928 if (plugin.get()) | |
| 929 plugin->PopPopupsEnabledState(); | |
| 930 } | |
| 931 | |
| 932 void NPN_PluginThreadAsyncCall(NPP id, | |
| 933 void (*func)(void*), | |
| 934 void* user_data) { | |
| 935 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
| 936 if (plugin.get()) | |
| 937 plugin->PluginThreadAsyncCall(func, user_data); | |
| 938 } | |
| 939 | |
| 940 NPError NPN_GetValueForURL(NPP id, | |
| 941 NPNURLVariable variable, | |
| 942 const char* url, | |
| 943 char** value, | |
| 944 uint32_t* len) { | |
| 945 if (!id) | |
| 946 return NPERR_INVALID_PARAM; | |
| 947 | |
| 948 if (!url || !*url || !len) | |
| 949 return NPERR_INVALID_URL; | |
| 950 | |
| 951 *len = 0; | |
| 952 std::string result; | |
| 953 | |
| 954 switch (variable) { | |
| 955 case NPNURLVProxy: { | |
| 956 result = "DIRECT"; | |
| 957 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
| 958 if (!plugin.get()) | |
| 959 return NPERR_GENERIC_ERROR; | |
| 960 | |
| 961 WebPlugin* webplugin = plugin->webplugin(); | |
| 962 if (!webplugin) | |
| 963 return NPERR_GENERIC_ERROR; | |
| 964 | |
| 965 if (!webplugin->FindProxyForUrl(GURL(std::string(url)), &result)) | |
| 966 return NPERR_GENERIC_ERROR; | |
| 967 break; | |
| 968 } | |
| 969 case NPNURLVCookie: { | |
| 970 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
| 971 if (!plugin.get()) | |
| 972 return NPERR_GENERIC_ERROR; | |
| 973 | |
| 974 WebPlugin* webplugin = plugin->webplugin(); | |
| 975 if (!webplugin) | |
| 976 return NPERR_GENERIC_ERROR; | |
| 977 | |
| 978 // Bypass third-party cookie blocking by using the url as the | |
| 979 // first_party_for_cookies. | |
| 980 GURL cookies_url((std::string(url))); | |
| 981 result = webplugin->GetCookies(cookies_url, cookies_url); | |
| 982 break; | |
| 983 } | |
| 984 default: | |
| 985 return NPERR_GENERIC_ERROR; | |
| 986 } | |
| 987 | |
| 988 // Allocate this using the NPAPI allocator. The plugin will call | |
| 989 // NPN_Free to free this. | |
| 990 *value = static_cast<char*>(NPN_MemAlloc(result.length() + 1)); | |
| 991 base::strlcpy(*value, result.c_str(), result.length() + 1); | |
| 992 *len = result.length(); | |
| 993 | |
| 994 return NPERR_NO_ERROR; | |
| 995 } | |
| 996 | |
| 997 NPError NPN_SetValueForURL(NPP id, | |
| 998 NPNURLVariable variable, | |
| 999 const char* url, | |
| 1000 const char* value, | |
| 1001 uint32_t len) { | |
| 1002 if (!id) | |
| 1003 return NPERR_INVALID_PARAM; | |
| 1004 | |
| 1005 if (!url || !*url) | |
| 1006 return NPERR_INVALID_URL; | |
| 1007 | |
| 1008 switch (variable) { | |
| 1009 case NPNURLVCookie: { | |
| 1010 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
| 1011 if (!plugin.get()) | |
| 1012 return NPERR_GENERIC_ERROR; | |
| 1013 | |
| 1014 WebPlugin* webplugin = plugin->webplugin(); | |
| 1015 if (!webplugin) | |
| 1016 return NPERR_GENERIC_ERROR; | |
| 1017 | |
| 1018 std::string cookie(value, len); | |
| 1019 GURL cookies_url((std::string(url))); | |
| 1020 webplugin->SetCookie(cookies_url, cookies_url, cookie); | |
| 1021 return NPERR_NO_ERROR; | |
| 1022 } | |
| 1023 case NPNURLVProxy: | |
| 1024 // We don't support setting proxy values, fall through... | |
| 1025 break; | |
| 1026 default: | |
| 1027 // Fall through and return an error... | |
| 1028 break; | |
| 1029 } | |
| 1030 | |
| 1031 return NPERR_GENERIC_ERROR; | |
| 1032 } | |
| 1033 | |
| 1034 NPError NPN_GetAuthenticationInfo(NPP id, | |
| 1035 const char* protocol, | |
| 1036 const char* host, | |
| 1037 int32_t port, | |
| 1038 const char* scheme, | |
| 1039 const char* realm, | |
| 1040 char** username, | |
| 1041 uint32_t* ulen, | |
| 1042 char** password, | |
| 1043 uint32_t* plen) { | |
| 1044 if (!id || !protocol || !host || !scheme || !realm || !username || | |
| 1045 !ulen || !password || !plen) | |
| 1046 return NPERR_INVALID_PARAM; | |
| 1047 | |
| 1048 // TODO: implement me (bug 23928) | |
| 1049 return NPERR_GENERIC_ERROR; | |
| 1050 } | |
| 1051 | |
| 1052 uint32_t NPN_ScheduleTimer(NPP id, | |
| 1053 uint32_t interval, | |
| 1054 NPBool repeat, | |
| 1055 void (*func)(NPP id, uint32_t timer_id)) { | |
| 1056 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
| 1057 if (!plugin.get()) | |
| 1058 return 0; | |
| 1059 | |
| 1060 return plugin->ScheduleTimer(interval, repeat, func); | |
| 1061 } | |
| 1062 | |
| 1063 void NPN_UnscheduleTimer(NPP id, uint32_t timer_id) { | |
| 1064 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
| 1065 if (plugin.get()) | |
| 1066 plugin->UnscheduleTimer(timer_id); | |
| 1067 } | |
| 1068 | |
| 1069 NPError NPN_PopUpContextMenu(NPP id, NPMenu* menu) { | |
| 1070 if (!menu) | |
| 1071 return NPERR_INVALID_PARAM; | |
| 1072 | |
| 1073 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
| 1074 if (plugin.get()) { | |
| 1075 return plugin->PopUpContextMenu(menu); | |
| 1076 } | |
| 1077 NOTREACHED(); | |
| 1078 return NPERR_GENERIC_ERROR; | |
| 1079 } | |
| 1080 | |
| 1081 NPBool NPN_ConvertPoint(NPP id, double sourceX, double sourceY, | |
| 1082 NPCoordinateSpace sourceSpace, | |
| 1083 double *destX, double *destY, | |
| 1084 NPCoordinateSpace destSpace) { | |
| 1085 scoped_refptr<PluginInstance> plugin(FindInstance(id)); | |
| 1086 if (plugin.get()) { | |
| 1087 return plugin->ConvertPoint( | |
| 1088 sourceX, sourceY, sourceSpace, destX, destY, destSpace); | |
| 1089 } | |
| 1090 NOTREACHED(); | |
| 1091 return false; | |
| 1092 } | |
| 1093 | |
| 1094 NPBool NPN_HandleEvent(NPP id, void *event, NPBool handled) { | |
| 1095 // TODO: Implement advanced key handling: http://crbug.com/46578 | |
| 1096 NOTIMPLEMENTED(); | |
| 1097 return false; | |
| 1098 } | |
| 1099 | |
| 1100 NPBool NPN_UnfocusInstance(NPP id, NPFocusDirection direction) { | |
| 1101 // TODO: Implement advanced key handling: http://crbug.com/46578 | |
| 1102 NOTIMPLEMENTED(); | |
| 1103 return false; | |
| 1104 } | |
| 1105 | |
| 1106 void NPN_URLRedirectResponse(NPP instance, void* notify_data, NPBool allow) { | |
| 1107 scoped_refptr<PluginInstance> plugin(FindInstance(instance)); | |
| 1108 if (plugin.get()) { | |
| 1109 plugin->URLRedirectResponse(!!allow, notify_data); | |
| 1110 } | |
| 1111 } | |
| 1112 | |
| 1113 } // extern "C" | |
| OLD | NEW |