Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7)

Side by Side Diff: webkit/glue/plugins/plugin_host.cc

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

Powered by Google App Engine
This is Rietveld 408576698