summaryrefslogtreecommitdiffstats
path: root/webkit
diff options
context:
space:
mode:
authoramanda@chromium.org <amanda@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-21 19:57:44 +0000
committeramanda@chromium.org <amanda@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-21 19:57:44 +0000
commit979cb0e4846b5420ca417dc05f2642c5f79f795f (patch)
tree74167ea5e2841a66c0739e2d1a3cdfcbd8dd0b11 /webkit
parent22927adeb7d392dfee17a90657f51bf12d8a5766 (diff)
downloadchromium_src-979cb0e4846b5420ca417dc05f2642c5f79f795f.zip
chromium_src-979cb0e4846b5420ca417dc05f2642c5f79f795f.tar.gz
chromium_src-979cb0e4846b5420ca417dc05f2642c5f79f795f.tar.bz2
Remove the temporary Mac plugin whitelist.
Support Mac NPAPI drawing and event model negotiation. Implement a fallback Quickdraw drawing model implementation so that old plugins don't crash. This change does not address keyboard input issues (see issue 19194), just display issues. BUG=12030 TEST=Quickdraw based plugins (such as the QuickTime plugin) should not crash when invoked, and may even display properly. Review URL: http://codereview.chromium.org/211031 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@26724 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit')
-rw-r--r--webkit/glue/plugins/plugin_host.cc36
-rw-r--r--webkit/glue/plugins/plugin_instance.cc4
-rw-r--r--webkit/glue/plugins/plugin_instance.h11
-rw-r--r--webkit/glue/plugins/plugin_list_mac.mm13
-rw-r--r--webkit/glue/plugins/webplugin_delegate_impl.h4
-rw-r--r--webkit/glue/plugins/webplugin_delegate_impl_mac.mm177
6 files changed, 203 insertions, 42 deletions
diff --git a/webkit/glue/plugins/plugin_host.cc b/webkit/glue/plugins/plugin_host.cc
index 27445a5..a6f0205 100644
--- a/webkit/glue/plugins/plugin_host.cc
+++ b/webkit/glue/plugins/plugin_host.cc
@@ -784,6 +784,14 @@ NPError NPN_GetValue(NPP id, NPNVariable variable, void *value) {
break;
}
#if defined(OS_MACOSX)
+ case NPNVpluginDrawingModel:
+ {
+ // return the drawing model that was negotiated when we initialized
+ scoped_refptr<NPAPI::PluginInstance> plugin = FindInstance(id);
+ *reinterpret_cast<int*>(value) = plugin->drawing_model();
+ rv = NPERR_NO_ERROR;
+ break;
+ }
case NPNVsupportsQuickDrawBool:
{
// we do not support the QuickDraw drawing model
@@ -851,15 +859,35 @@ NPError NPN_SetValue(NPP id, NPPVariable variable, void *value) {
DLOG(INFO) << "NPN_SetValue(NPPVpluginKeepLibraryInMemory) is not implemented.";
return NPERR_GENERIC_ERROR;
#if defined(OS_MACOSX)
- case NPNVpluginDrawingModel:
- // we only support the CoreGraphics drawing model
- if (reinterpret_cast<int>(value) == NPDrawingModelCoreGraphics)
+ case NPPVpluginDrawingModel:
+ {
+ // we only admit to supporting the CoreGraphics drawing model. The logic
+ // here is that our QuickDraw plugin support is so rudimentary that we
+ // only want to use it as a fallback to keep plugins from crashing: if
+ // a plugin knows enough to ask, we want them to use CoreGraphics.
+ int model = reinterpret_cast<int>(value);
+ if (model == NPDrawingModelCoreGraphics) {
+ plugin->set_drawing_model(model);
return NPERR_NO_ERROR;
+ }
return NPERR_GENERIC_ERROR;
+ }
+ case NPPVpluginEventModel:
+ {
+ // we only support the Carbon event model
+ int model = reinterpret_cast<int>(value);
+ switch (model) {
+ case NPNVsupportsCarbonBool:
+ plugin->set_event_model(model);
+ return NPERR_NO_ERROR;
+ break;
+ }
+ return NPERR_GENERIC_ERROR;
+ }
#endif
default:
// TODO: implement me
- DLOG(INFO) << "NPN_SetValue(" << variable << ") is not implemented.";
+ LOG(WARNING) << "NPN_SetValue(" << variable << ") is not implemented.";
break;
}
diff --git a/webkit/glue/plugins/plugin_instance.cc b/webkit/glue/plugins/plugin_instance.cc
index ad8c9bf..42abdc5 100644
--- a/webkit/glue/plugins/plugin_instance.cc
+++ b/webkit/glue/plugins/plugin_instance.cc
@@ -42,6 +42,10 @@ PluginInstance::PluginInstance(PluginLib *plugin, const std::string &mime_type)
webplugin_(0),
mime_type_(mime_type),
use_mozilla_user_agent_(false),
+#if defined (OS_MACOSX)
+ drawing_model_(0),
+ event_model_(0),
+#endif
message_loop_(MessageLoop::current()),
load_manually_(false),
in_close_streams_(false) {
diff --git a/webkit/glue/plugins/plugin_instance.h b/webkit/glue/plugins/plugin_instance.h
index 352dab5..a724957 100644
--- a/webkit/glue/plugins/plugin_instance.h
+++ b/webkit/glue/plugins/plugin_instance.h
@@ -101,6 +101,13 @@ class PluginInstance : public base::RefCountedThreadSafe<PluginInstance> {
NPAPI::PluginLib* plugin_lib() { return plugin_; }
+#if defined(OS_MACOSX)
+ int drawing_model() { return drawing_model_; }
+ void set_drawing_model(int value) { drawing_model_ = value; }
+ int event_model() { return event_model_; }
+ void set_event_model(int value) { event_model_ = value; }
+#endif
+
#if defined(OS_WIN)
// Handles a windows native message which this PluginInstance should deal
// with. Returns true if the event is handled, false otherwise.
@@ -238,6 +245,10 @@ class PluginInstance : public base::RefCountedThreadSafe<PluginInstance> {
#if defined(OS_WIN)
scoped_refptr<MozillaExtensionApi> mozilla_extenstions_;
#endif
+#if defined(OS_MACOSX)
+ int drawing_model_;
+ int event_model_;
+#endif
MessageLoop* message_loop_;
scoped_refptr<PluginStreamUrl> plugin_data_stream_;
diff --git a/webkit/glue/plugins/plugin_list_mac.mm b/webkit/glue/plugins/plugin_list_mac.mm
index c470c5a..518d37f 100644
--- a/webkit/glue/plugins/plugin_list_mac.mm
+++ b/webkit/glue/plugins/plugin_list_mac.mm
@@ -76,19 +76,6 @@ bool PluginList::ShouldLoadPlugin(const WebPluginInfo& info,
return false;
}
- // For now, only load plugins that we know are working reasonably well.
- // Anything using QuickDraw-based drawing, for example, would crash
- // immediately.
-
- std::string plugin_name = WideToUTF8(info.name);
- if (!(plugin_name == "WebKit Test PlugIn" ||
- plugin_name == "Shockwave Flash" ||
- plugin_name == "Picasa" ||
- plugin_name == "Google Talk Browser Plugin" ||
- plugin_name == "Google Talk NPAPI Plugin")) {
- return false;
- }
-
// Hierarchy check
// (we're loading plugins hierarchically from Library folders, so plugins we
// encounter earlier must override plugins we encounter later)
diff --git a/webkit/glue/plugins/webplugin_delegate_impl.h b/webkit/glue/plugins/webplugin_delegate_impl.h
index 6d53339..56f6264 100644
--- a/webkit/glue/plugins/webplugin_delegate_impl.h
+++ b/webkit/glue/plugins/webplugin_delegate_impl.h
@@ -237,6 +237,10 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate {
NPWindow window_;
#if defined(OS_MACOSX)
NP_CGContext cg_context_;
+#ifndef NP_NO_QUICKDRAW
+ NP_Port qd_port_;
+ GWorldPtr qd_world_;
+#endif
#endif
gfx::Rect window_rect_;
gfx::Rect clip_rect_;
diff --git a/webkit/glue/plugins/webplugin_delegate_impl_mac.mm b/webkit/glue/plugins/webplugin_delegate_impl_mac.mm
index ecb2c6f..e40546c 100644
--- a/webkit/glue/plugins/webplugin_delegate_impl_mac.mm
+++ b/webkit/glue/plugins/webplugin_delegate_impl_mac.mm
@@ -27,6 +27,14 @@
#include "webkit/glue/plugins/plugin_stream_url.h"
#include "webkit/glue/webkit_glue.h"
+// If we're compiling support for the QuickDraw drawing model, turn off GCC
+// warnings about deprecated functions (since QuickDraw is a deprecated API).
+// According to the GCC documentation, this can only be done per file, not
+// pushed and popped like some options can be.
+#ifndef NP_NO_QUICKDRAW
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+
using webkit_glue::WebPlugin;
using webkit_glue::WebPluginDelegate;
using webkit_glue::WebPluginResourceClient;
@@ -98,11 +106,21 @@ WebPluginDelegateImpl::WebPluginDelegateImpl(
user_gesture_msg_factory_(this),
null_event_factory_(this),
last_mouse_x_(0),
- last_mouse_y_(0) {
+ last_mouse_y_(0),
+ qd_world_(0) {
memset(&window_, 0, sizeof(window_));
+#ifndef NP_NO_QUICKDRAW
+ memset(&qd_port_, 0, sizeof(qd_port_));
+#endif
}
WebPluginDelegateImpl::~WebPluginDelegateImpl() {
+#ifndef NP_NO_QUICKDRAW
+ if (qd_port_.port) {
+ DisposeGWorld(qd_port_.port);
+ DisposeGWorld(qd_world_);
+ }
+#endif
FakePluginWindowTracker::SharedInstance()->RemoveFakeWindowForDelegate(
this, reinterpret_cast<WindowRef>(cg_context_.window));
DestroyInstance();
@@ -151,8 +169,22 @@ bool WebPluginDelegateImpl::Initialize(const GURL& url,
Rect window_bounds = { 0, 0, window_rect_.height(), window_rect_.width() };
SetWindowBounds(reinterpret_cast<WindowRef>(cg_context_.window),
kWindowContentRgn, &window_bounds);
- window_.window = &cg_context_;
- window_.type = NPWindowTypeWindow;
+
+ switch (instance_->drawing_model()) {
+#ifndef NP_NO_QUICKDRAW
+ case NPDrawingModelQuickDraw:
+ window_.window = &qd_port_;
+ window_.type = NPWindowTypeDrawable;
+ break;
+#endif
+ case NPDrawingModelCoreGraphics:
+ window_.window = &cg_context_;
+ window_.type = NPWindowTypeDrawable;
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
plugin->SetWindow(NULL);
plugin_url_ = url.spec();
@@ -199,6 +231,32 @@ void WebPluginDelegateImpl::UpdateContext(CGContextRef context) {
// changes.
if (context != cg_context_.context) {
cg_context_.context = context;
+#ifndef NP_NO_QUICKDRAW
+ if (instance()->drawing_model() == NPDrawingModelQuickDraw) {
+ if (qd_port_.port) {
+ DisposeGWorld(qd_port_.port);
+ DisposeGWorld(qd_world_);
+ qd_port_.port = NULL;
+ qd_world_ = NULL;
+ }
+ Rect window_bounds = {
+ 0, 0, window_rect_.height(), window_rect_.width()
+ };
+ // Create a GWorld pointing at the same bits as our CGContextRef
+ NewGWorldFromPtr(&qd_world_, k32BGRAPixelFormat, &window_bounds,
+ NULL, NULL, 0,
+ static_cast<Ptr>(CGBitmapContextGetData(context)),
+ static_cast<SInt32>(CGBitmapContextGetBytesPerRow(context)));
+ // Create a GWorld for the plugin to paint into whenever it wants
+ NewGWorld(&qd_port_.port, k32ARGBPixelFormat, &window_bounds,
+ NULL, NULL, kNativeEndianPixMap);
+ SetGWorld(qd_port_.port, NULL);
+ // Fill with black
+ ForeColor(blackColor);
+ BackColor(whiteColor);
+ PaintRect(&window_bounds);
+ }
+#endif
WindowlessSetWindow(true);
}
}
@@ -296,25 +354,62 @@ void WebPluginDelegateImpl::WindowlessPaint(gfx::NativeDrawingContext context,
static StatsRate plugin_paint("Plugin.Paint");
StatsScope<StatsRate> scope(plugin_paint);
- // We save and restore the NSGraphicsContext state in case the plugin uses
- // Cocoa drawing.
- [NSGraphicsContext saveGraphicsState];
- [NSGraphicsContext setCurrentContext:[NSGraphicsContext
- graphicsContextWithGraphicsPort:context
- flipped:YES]];
- CGContextSaveGState(context);
-
- NPEvent paint_event;
- paint_event.what = updateEvt;
- paint_event.message = reinterpret_cast<uint32>(cg_context_.window);
- paint_event.when = TickCount();
- paint_event.where.h = 0;
- paint_event.where.v = 0;
- paint_event.modifiers = 0;
- instance()->NPP_HandleEvent(&paint_event);
-
- CGContextRestoreGState(context);
- [NSGraphicsContext restoreGraphicsState];
+ switch (instance()->drawing_model()) {
+#ifndef NP_NO_QUICKDRAW
+ case NPDrawingModelQuickDraw:
+ {
+ // Plugins using the QuickDraw drawing model do not restrict their
+ // drawing to update events the way that CoreGraphics-based plugins
+ // do. When we are asked to paint, we therefore just copy from the
+ // plugin's persistent offscreen GWorld into our shared memory bitmap
+ // context.
+ Rect window_bounds = {
+ 0, 0, window_rect_.height(), window_rect_.width()
+ };
+ PixMapHandle plugin_pixmap = GetGWorldPixMap(qd_port_.port);
+ if (LockPixels(plugin_pixmap)) {
+ PixMapHandle shared_pixmap = GetGWorldPixMap(qd_world_);
+ if (LockPixels(shared_pixmap)) {
+ SetGWorld(qd_world_, NULL);
+ // Set foreground and background colors to avoid "colorizing" the
+ // image.
+ ForeColor(blackColor);
+ BackColor(whiteColor);
+ CopyBits(reinterpret_cast<BitMap*>(*plugin_pixmap),
+ reinterpret_cast<BitMap*>(*shared_pixmap),
+ &window_bounds, &window_bounds, srcCopy, NULL);
+ UnlockPixels(shared_pixmap);
+ }
+ UnlockPixels(plugin_pixmap);
+ }
+ break;
+ }
+#endif
+ case NPDrawingModelCoreGraphics:
+ {
+ NPEvent paint_event;
+
+ // Save and restore the NSGraphicsContext state in case the plugin uses
+ // Cocoa drawing.
+ [NSGraphicsContext saveGraphicsState];
+ [NSGraphicsContext setCurrentContext:
+ [NSGraphicsContext graphicsContextWithGraphicsPort:context
+ flipped:YES]];
+ CGContextSaveGState(context);
+
+ paint_event.what = updateEvt;
+ paint_event.message = reinterpret_cast<uint32>(cg_context_.window);
+ paint_event.when = TickCount();
+ paint_event.where.h = 0;
+ paint_event.where.v = 0;
+ paint_event.modifiers = 0;
+ instance()->NPP_HandleEvent(&paint_event);
+
+ CGContextRestoreGState(context);
+ [NSGraphicsContext restoreGraphicsState];
+ break;
+ }
+ }
}
// Moves our dummy window to the given offset relative to the last known
@@ -364,6 +459,7 @@ void WebPluginDelegateImpl::WindowlessSetWindow(bool force_set_window) {
window_rect_.y(), window_rect_.width(), window_rect_.height());
NPError err = instance()->NPP_SetWindow(&window_);
+
DCHECK(err == NPERR_NO_ERROR);
}
@@ -515,6 +611,7 @@ bool WebPluginDelegateImpl::HandleInputEvent(const WebInputEvent& event,
NPEvent np_event = {0};
if (!NPEventFromWebInputEvent(event, &np_event)) {
+ LOG(WARNING) << "NPEventFromWebInputEvent failed";
return false;
}
np_event.when = TickCount();
@@ -533,9 +630,20 @@ bool WebPluginDelegateImpl::HandleInputEvent(const WebInputEvent& event,
UpdateWindowLocation(reinterpret_cast<WindowRef>(cg_context_.window),
*mouse_event);
}
- CGContextSaveGState(cg_context_.context);
- bool ret = instance()->NPP_HandleEvent(&np_event) != 0;
- CGContextRestoreGState(cg_context_.context);
+ bool ret = false;
+ switch (instance()->drawing_model()) {
+#ifndef NP_NO_QUICKDRAW
+ case NPDrawingModelQuickDraw:
+ SetGWorld(qd_port_.port, NULL);
+ ret = instance()->NPP_HandleEvent(&np_event) != 0;
+ break;
+#endif
+ case NPDrawingModelCoreGraphics:
+ CGContextSaveGState(cg_context_.context);
+ ret = instance()->NPP_HandleEvent(&np_event) != 0;
+ CGContextRestoreGState(cg_context_.context);
+ break;
+ }
return ret;
}
@@ -561,6 +669,16 @@ WebPluginResourceClient* WebPluginDelegateImpl::CreateResourceClient(
}
void WebPluginDelegateImpl::OnNullEvent() {
+ // Dispatch any pending Carbon events so that the plugin's event handlers
+ // will get called on any windows it has created.
+ EventRef event;
+ while (ReceiveNextEvent(
+ 0, NULL, kEventDurationNoWait, kEventRemoveFromQueue, &event) == noErr) {
+ SendEventToEventTarget(event, GetEventDispatcherTarget());
+ ReleaseEvent(event);
+ }
+
+ // Send an idle event so that the plugin can do background work
NPEvent np_event = {0};
np_event.what = nullEvent;
np_event.when = TickCount();
@@ -571,6 +689,15 @@ void WebPluginDelegateImpl::OnNullEvent() {
np_event.where.v = last_mouse_y_;
instance()->NPP_HandleEvent(&np_event);
+#ifndef NP_NO_QUICKDRAW
+ // Quickdraw-based plugins can draw at any time, so tell the renderer to
+ // repaint.
+ // TODO: only do this if the contents of the offscreen GWorld has changed,
+ // so as not to spam the renderer with an unchanging image.
+ if (instance_->drawing_model() == NPDrawingModelQuickDraw)
+ instance()->webplugin()->Invalidate();
+#endif
+
MessageLoop::current()->PostDelayedTask(FROM_HERE,
null_event_factory_.NewRunnableMethod(
&WebPluginDelegateImpl::OnNullEvent),