summaryrefslogtreecommitdiffstats
path: root/webkit/glue
diff options
context:
space:
mode:
authoramanda@chromium.org <amanda@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-11 01:57:28 +0000
committeramanda@chromium.org <amanda@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-11 01:57:28 +0000
commit6bf1a81cdfcc48f20cf53c2601f4456f2d9d30ef (patch)
tree7bedf19228a20b83189ab96e617e72210991c7c4 /webkit/glue
parent7e05f6c4baad4f81e06835b83febe2784568ebe1 (diff)
downloadchromium_src-6bf1a81cdfcc48f20cf53c2601f4456f2d9d30ef.zip
chromium_src-6bf1a81cdfcc48f20cf53c2601f4456f2d9d30ef.tar.gz
chromium_src-6bf1a81cdfcc48f20cf53c2601f4456f2d9d30ef.tar.bz2
Wire up windowless plugins. Mostly Mac related, some cross
platform aspects. BUG=10809 TEST=none Review URL: http://codereview.chromium.org/113637 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@20453 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/glue')
-rw-r--r--webkit/glue/plugins/plugin_host.cc24
-rw-r--r--webkit/glue/plugins/webplugin_delegate_impl.h4
-rw-r--r--webkit/glue/plugins/webplugin_delegate_impl_mac.mm375
3 files changed, 236 insertions, 167 deletions
diff --git a/webkit/glue/plugins/plugin_host.cc b/webkit/glue/plugins/plugin_host.cc
index 2e1c233..40b2e1e 100644
--- a/webkit/glue/plugins/plugin_host.cc
+++ b/webkit/glue/plugins/plugin_host.cc
@@ -600,22 +600,19 @@ void NPN_InvalidateRect(NPP id, NPRect *invalidRect) {
DCHECK(plugin.get() != NULL);
if (plugin.get() && plugin->webplugin()) {
if (invalidRect) {
- if (!plugin->windowless()) {
#if defined(OS_WIN)
+ if (!plugin->windowless()) {
RECT rect = {0};
rect.left = invalidRect->left;
rect.right = invalidRect->right;
rect.top = invalidRect->top;
rect.bottom = invalidRect->bottom;
::InvalidateRect(plugin->window_handle(), &rect, FALSE);
-#elif defined(OS_MACOSX)
- NOTIMPLEMENTED();
-#else
- NOTIMPLEMENTED();
-#endif
return;
}
-
+#elif defined(OS_LINUX)
+ NOTIMPLEMENTED();
+#endif
gfx::Rect rect(invalidRect->left,
invalidRect->top,
invalidRect->right - invalidRect->left,
@@ -633,8 +630,13 @@ void NPN_InvalidateRegion(NPP id, NPRegion invalidRegion) {
//
// Similar to NPN_InvalidateRect.
- // TODO: implement me
- DLOG(INFO) << "NPN_InvalidateRegion is not implemented yet.";
+ // TODO: this is overkill--add platform-specific region handling (at the
+ // very least, fetch the region's bounding box and pass it to InvalidateRect).
+ scoped_refptr<NPAPI::PluginInstance> plugin = FindInstance(id);
+ DCHECK(plugin.get() != NULL);
+ if (plugin.get() && plugin->webplugin()) {
+ plugin->webplugin()->Invalidate();
+ }
}
void NPN_ForceRedraw(NPP id) {
@@ -652,10 +654,8 @@ void NPN_ForceRedraw(NPP id) {
// settings. The HDC settings must be restored whenever control returns
// back to the browser, either before returning from NPP_HandleEvent or
// before calling a drawing-related netscape method.
- //
- // TODO: implement me
- DLOG(INFO) << "NPN_ForceRedraw is not implemented yet.";
+ NOTIMPLEMENTED();
}
NPError NPN_GetValue(NPP id, NPNVariable variable, void *value) {
diff --git a/webkit/glue/plugins/webplugin_delegate_impl.h b/webkit/glue/plugins/webplugin_delegate_impl.h
index a6f0715..35302dc7 100644
--- a/webkit/glue/plugins/webplugin_delegate_impl.h
+++ b/webkit/glue/plugins/webplugin_delegate_impl.h
@@ -95,6 +95,7 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
NPAPI::PluginInstance *instance);
~WebPluginDelegateImpl();
+#if !defined(OS_MACOSX)
//--------------------------
// used for windowed plugins
void WindowedUpdateGeometry(const gfx::Rect& window_rect,
@@ -115,6 +116,7 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
// Tells the plugin about the current state of the window.
// See NPAPI NPP_SetWindow for more information.
void WindowedSetWindow();
+#endif
#if defined(OS_WIN)
// Registers the window class for our window
@@ -153,10 +155,10 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
// Closes down and destroys our plugin instance.
void DestroyInstance();
+#if !defined(OS_MACOSX)
// used for windowed plugins
gfx::PluginWindowHandle windowed_handle_;
bool windowed_did_set_window_;
-#if defined(OS_WIN)
gfx::Rect windowed_last_pos_;
#endif
diff --git a/webkit/glue/plugins/webplugin_delegate_impl_mac.mm b/webkit/glue/plugins/webplugin_delegate_impl_mac.mm
index 414d635..9232fca 100644
--- a/webkit/glue/plugins/webplugin_delegate_impl_mac.mm
+++ b/webkit/glue/plugins/webplugin_delegate_impl_mac.mm
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#import <Cocoa/Cocoa.h>
+
#include "config.h"
#include "webkit/glue/plugins/webplugin_delegate_impl.h"
@@ -29,31 +31,27 @@ using WebKit::WebKeyboardEvent;
using WebKit::WebInputEvent;
using WebKit::WebMouseEvent;
-namespace {
+// Important implementation notes: The Mac definition of NPAPI, particularly
+// the distinction between windowed and windowless modes, differs from the
+// Windows and Linux definitions. Most of those differences are
+// accomodated by the WebPluginDelegate class.
-const wchar_t kWebPluginDelegateProperty[] = L"WebPluginDelegateProperty";
-const wchar_t kPluginNameAtomProperty[] = L"PluginNameAtom";
-const wchar_t kDummyActivationWindowName[] = L"DummyWindowForActivation";
-const wchar_t kPluginOrigProc[] = L"OriginalPtr";
-const wchar_t kPluginFlashThrottle[] = L"FlashThrottle";
+namespace {
-// The fastest we are willing to process WM_USER+1 events for Flash.
+// The fastest we are willing to process idle events for Flash.
// Flash can easily exceed the limits of our CPU if we don't throttle it.
// The throttle has been chosen by testing various delays and compromising
// on acceptable Flash performance and reasonable CPU consumption.
//
-// I'd like to make the throttle delay variable, based on the amount of
+// We'd like to make the throttle delay variable, based on the amount of
// time currently required to paint Flash plugins. There isn't a good
// way to count the time spent in aggregate plugin painting, however, so
// this seems to work well enough.
-const int kFlashWMUSERMessageThrottleDelayMs = 5;
+const int kFlashIdleThrottleDelayMs = 20; // 20ms (50Hz)
// The current instance of the plugin which entered the modal loop.
WebPluginDelegateImpl* g_current_plugin_instance = NULL;
-// base::LazyInstance<std::list<MSG> > g_throttle_queue(base::LINKER_INITIALIZED);
-
-
} // namespace
WebPluginDelegate* WebPluginDelegate::Create(
@@ -81,27 +79,20 @@ WebPluginDelegateImpl::WebPluginDelegateImpl(
instance_(instance),
quirks_(0),
plugin_(NULL),
- windowless_(false),
- windowed_handle_(NULL),
- windowed_did_set_window_(false),
+ // all Mac plugins are "windowless" in the Windows/X11 sense
+ windowless_(true),
windowless_needs_set_window_(true),
handle_event_depth_(0),
user_gesture_message_posted_(this),
user_gesture_msg_factory_(this) {
memset(&window_, 0, sizeof(window_));
-
- const WebPluginInfo& plugin_info = instance_->plugin_lib()->plugin_info();
- std::string filename =
- StringToLowerASCII(plugin_info.path.BaseName().value());
-
- // plugin_module_handle_ = ::GetModuleHandle(plugin_info.path.value().c_str());
}
WebPluginDelegateImpl::~WebPluginDelegateImpl() {
DestroyInstance();
- if (!windowless_)
- WindowedDestroyWindow();
+ if (cg_context_.window)
+ DisposeWindow(cg_context_.window);
}
void WebPluginDelegateImpl::PluginDestroyed() {
@@ -128,20 +119,11 @@ bool WebPluginDelegateImpl::Initialize(const GURL& url,
if (!start_result)
return false;
- windowless_ = instance_->windowless();
- if (windowless_) {
- // For windowless plugins we should set the containing window handle
- // as the instance window handle. This is what Safari does. Not having
- // a valid window handle causes subtle bugs with plugins which retreive
- // the window handle and validate the same. The window handle can be
- // retreived via NPN_GetValue of NPNVnetscapeWindow.
- // instance_->set_window_handle(parent_);
- } else {
- if (!WindowedCreatePlugin())
- return false;
- }
+ cg_context_.window = NULL;
+ window_.window = &cg_context_;
+ window_.type = NPWindowTypeDrawable;
- // plugin->SetWindow(windowed_handle_);
+ plugin->SetWindow(NULL);
plugin_url_ = url.spec();
return true;
@@ -154,18 +136,8 @@ void WebPluginDelegateImpl::DestroyInstance() {
// this before calling set_web_plugin(NULL) because the
// instance uses the helper to do the download.
instance_->CloseStreams();
-
- window_.window = NULL;
- instance_->NPP_SetWindow(&window_);
-
instance_->NPP_Destroy();
-
instance_->set_web_plugin(NULL);
-
- if (instance_->plugin_lib()) {
- // Unpatch if this is the last plugin instance.
- }
-
instance_ = 0;
}
}
@@ -173,11 +145,36 @@ void WebPluginDelegateImpl::DestroyInstance() {
void WebPluginDelegateImpl::UpdateGeometry(
const gfx::Rect& window_rect,
const gfx::Rect& clip_rect) {
- if (windowless_) {
- WindowlessUpdateGeometry(window_rect, clip_rect);
- } else {
- WindowedUpdateGeometry(window_rect, clip_rect);
+
+ if (!window_rect.IsEmpty()) {
+ NSPoint windowOffset = {0.0, 0.0};
+ Rect window_bounds;
+ window_bounds.top = window_rect.y() + windowOffset.y;
+ window_bounds.left = window_rect.x() + windowOffset.x;
+ window_bounds.bottom = window_rect.y() + window_rect.height();
+ window_bounds.right = window_rect.x() + window_rect.width();
+
+ if (!cg_context_.window) {
+ // For all plugins we create a placeholder offscreen window for the use
+ // of NPWindow. NPAPI on the Mac requires a Carbon WindowRef for the
+ // "browser window", even if we're not using the Quickdraw drawing model.
+ // Not having a valid window reference causes subtle bugs with plugins
+ // which retreive the NPWindow and validate the same. The NPWindow
+ // can be retreived via NPN_GetValue of NPNVnetscapeWindow.
+
+ WindowRef window_ref;
+ if (CreateNewWindow(kDocumentWindowClass,
+ kWindowStandardDocumentAttributes,
+ &window_bounds,
+ &window_ref) == noErr) {
+ cg_context_.window = window_ref;
+ }
+ } else {
+ SetWindowBounds(cg_context_.window, kWindowContentRgn, &window_bounds);
+ }
}
+
+ WindowlessUpdateGeometry(window_rect, clip_rect);
}
void WebPluginDelegateImpl::Paint(CGContextRef context, const gfx::Rect& rect) {
@@ -218,12 +215,6 @@ void WebPluginDelegateImpl::SendJavaScriptStream(const std::string& url,
void WebPluginDelegateImpl::DidReceiveManualResponse(
const std::string& url, const std::string& mime_type,
const std::string& headers, uint32 expected_length, uint32 last_modified) {
- if (!windowless_) {
- // Calling NPP_WriteReady before NPP_SetWindow causes movies to not load in
- // Flash. See http://b/issue?id=892174.
- DCHECK(windowed_did_set_window_);
- }
-
instance()->DidReceiveManualResponse(url, mime_type, headers,
expected_length, last_modified);
}
@@ -250,91 +241,6 @@ void WebPluginDelegateImpl::InstallMissingPlugin() {
instance()->NPP_HandleEvent(&evt);
}
-void WebPluginDelegateImpl::WindowedUpdateGeometry(
- const gfx::Rect& window_rect,
- const gfx::Rect& clip_rect) {
- if (WindowedReposition(window_rect, clip_rect) ||
- !windowed_did_set_window_) {
- // Let the plugin know that it has been moved
- WindowedSetWindow();
- }
-}
-
-bool WebPluginDelegateImpl::WindowedCreatePlugin() {
- DCHECK(!windowed_handle_);
-
- // create window
- if (windowed_handle_ == 0)
- return false;
-
- return true;
-}
-
-void WebPluginDelegateImpl::WindowedDestroyWindow() {
- if (windowed_handle_ != NULL) {
- // destroy the window
- windowed_handle_ = 0;
- }
-}
-
-bool WebPluginDelegateImpl::WindowedReposition(
- const gfx::Rect& window_rect,
- const gfx::Rect& clip_rect) {
- if (!windowed_handle_) {
- NOTREACHED();
- return false;
- }
-
- if (window_rect_ == window_rect && clip_rect_ == clip_rect)
- return false;
-
- // Clipping is handled by WebPlugin.
- if (window_rect.size() != window_rect_.size()) {
- // resize window
- }
-
- window_rect_ = window_rect;
- clip_rect_ = clip_rect;
-
- // Ensure that the entire window gets repainted.
- // invalidate entire window
-
- return true;
-}
-
-void WebPluginDelegateImpl::WindowedSetWindow() {
- if (!instance_)
- return;
-
- if (!windowed_handle_) {
- NOTREACHED();
- return;
- }
-
- // instance()->set_window_handle(windowed_handle_);
-
- DCHECK(!instance()->windowless());
-
- window_.clipRect.top = clip_rect_.y();
- window_.clipRect.left = clip_rect_.x();
- window_.clipRect.bottom = clip_rect_.y() + clip_rect_.height();
- window_.clipRect.right = clip_rect_.x() + clip_rect_.width();
- window_.height = window_rect_.height();
- window_.width = window_rect_.width();
- window_.x = window_rect_.x();
- window_.y = window_rect_.y();
-
- cg_context_.context = NULL;
- cg_context_.window = NULL;
- window_.window = &cg_context_;
- window_.type = NPWindowTypeDrawable; // NPWindowTypeWindow;
-
- // Reset this flag before entering the instance in case of side-effects.
- windowed_did_set_window_ = true;
-
- NPError err = instance()->NPP_SetWindow(&window_);
-}
-
void WebPluginDelegateImpl::WindowlessUpdateGeometry(
const gfx::Rect& window_rect,
const gfx::Rect& clip_rect) {
@@ -349,20 +255,72 @@ void WebPluginDelegateImpl::WindowlessUpdateGeometry(
if (window_rect_ != window_rect) {
window_rect_ = window_rect;
- WindowlessSetWindow(true);
-
- NPEvent pos_changed_event;
-
- instance()->NPP_HandleEvent(&pos_changed_event);
+ window_.clipRect.top = clip_rect_.y();
+ window_.clipRect.left = clip_rect_.x();
+ window_.clipRect.bottom = clip_rect_.y() + clip_rect_.height();
+ window_.clipRect.right = clip_rect_.x() + clip_rect_.width();
+ window_.height = window_rect_.height();
+ window_.width = window_rect_.width();
+ window_.x = window_rect_.x();
+ window_.y = window_rect_.y();
+ window_.type = NPWindowTypeDrawable;
+ windowless_needs_set_window_ = true;
}
}
-void WebPluginDelegateImpl::WindowlessPaint(gfx::NativeDrawingContext hdc,
+void WebPluginDelegateImpl::WindowlessPaint(gfx::NativeDrawingContext context,
const gfx::Rect& damage_rect) {
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:NO]];
+
+ CGContextSaveGState(context);
+ cg_context_.context = context;
+ window_.window = &cg_context_;
+ window_.type = NPWindowTypeDrawable;
+ if (windowless_needs_set_window_) {
+ Rect window_bounds;
+ window_bounds.top = window_rect_.y();
+ window_bounds.left = window_rect_.x();
+ window_bounds.bottom = window_rect_.y() + window_rect_.height();
+ window_bounds.right = window_rect_.x() + window_rect_.width();
+ if (!cg_context_.window) {
+ // For all plugins we create a placeholder offscreen window for the use
+ // of NPWindow. NPAPI on the Mac requires a Carbon WindowRef for the
+ // "browser window", even if we're not using the Quickdraw drawing model.
+ // Not having a valid window reference causes subtle bugs with plugins
+ // which retreive the NPWindow and validate the same. The NPWindow
+ // can be retreived via NPN_GetValue of NPNVnetscapeWindow.
+
+ WindowRef window_ref;
+ if (CreateNewWindow(kDocumentWindowClass,
+ kWindowStandardDocumentAttributes,
+ &window_bounds,
+ &window_ref) == noErr) {
+ cg_context_.window = window_ref;
+ }
+ } else {
+ SetWindowBounds(cg_context_.window, kWindowContentRgn, &window_bounds);
+ }
+ instance()->NPP_SetWindow(&window_);
+ windowless_needs_set_window_ = false;
+ }
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];
}
void WebPluginDelegateImpl::WindowlessSetWindow(bool force_set_window) {
@@ -372,8 +330,6 @@ void WebPluginDelegateImpl::WindowlessSetWindow(bool force_set_window) {
if (window_rect_.IsEmpty()) // wait for geometry to be set.
return;
- DCHECK(instance()->windowless());
-
window_.clipRect.top = clip_rect_.y();
window_.clipRect.left = clip_rect_.x();
window_.clipRect.bottom = clip_rect_.y() + clip_rect_.height();
@@ -388,25 +344,136 @@ void WebPluginDelegateImpl::WindowlessSetWindow(bool force_set_window) {
// Reset this flag before entering the instance in case of side-effects.
windowless_needs_set_window_ = false;
+ Rect window_bounds;
+ window_bounds.top = window_rect_.y();
+ window_bounds.left = window_rect_.x();
+ window_bounds.bottom = window_rect_.y() + window_rect_.height();
+ window_bounds.right = window_rect_.x() + window_rect_.width();
+ if (!cg_context_.window) {
+ // For all plugins we create a placeholder offscreen window for the use
+ // of NPWindow. NPAPI on the Mac requires a Carbon WindowRef for the
+ // "browser window", even if we're not using the Quickdraw drawing model.
+ // Not having a valid window reference causes subtle bugs with plugins
+ // which retreive the NPWindow and validate the same. The NPWindow
+ // can be retreived via NPN_GetValue of NPNVnetscapeWindow.
+
+ WindowRef window_ref;
+ if (CreateNewWindow(kDocumentWindowClass,
+ kWindowStandardDocumentAttributes,
+ &window_bounds,
+ &window_ref) == noErr) {
+ cg_context_.window = window_ref;
+ }
+ } else {
+ SetWindowBounds(cg_context_.window, kWindowContentRgn, &window_bounds);
+ }
+
NPError err = instance()->NPP_SetWindow(&window_);
DCHECK(err == NPERR_NO_ERROR);
}
void WebPluginDelegateImpl::SetFocus() {
- DCHECK(instance()->windowless());
+ NPEvent focus_event = { 0 };
+ focus_event.what = NPEventType_GetFocusEvent;
+ focus_event.when = TickCount();
+ instance()->NPP_HandleEvent(&focus_event);
+}
- NPEvent focus_event;
+static bool NPEventFromWebMouseEvent(const WebMouseEvent& event,
+ NPEvent *np_event) {
+ np_event->where.h = event.windowX;
+ np_event->where.v = event.windowY;
+
+ if (event.modifiers & WebInputEvent::ControlKey)
+ np_event->modifiers |= controlKey;
+ if (event.modifiers & WebInputEvent::ShiftKey)
+ np_event->modifiers |= shiftKey;
+
+ switch (event.type) {
+ case WebInputEvent::MouseMove:
+ case WebInputEvent::MouseLeave:
+ case WebInputEvent::MouseEnter:
+ np_event->what = NPEventType_AdjustCursorEvent;
+ return true;
+ case WebInputEvent::MouseDown:
+ switch (event.button) {
+ case WebMouseEvent::ButtonLeft:
+ case WebMouseEvent::ButtonMiddle:
+ case WebMouseEvent::ButtonRight:
+ np_event->what = mouseDown;
+ break;
+ }
+ return true;
+ case WebInputEvent::MouseUp:
+ switch (event.button) {
+ case WebMouseEvent::ButtonLeft:
+ case WebMouseEvent::ButtonMiddle:
+ case WebMouseEvent::ButtonRight:
+ np_event->what = mouseUp;
+ break;
+ }
+ return true;
+ default:
+ NOTREACHED();
+ return false;
+ }
+}
- instance()->NPP_HandleEvent(&focus_event);
+static bool NPEventFromWebKeyboardEvent(const WebKeyboardEvent& event,
+ NPEvent *np_event) {
+ np_event->message = event.nativeKeyCode;
+
+ switch (event.type) {
+ case WebInputEvent::KeyDown:
+ np_event->what = keyDown;
+ return true;
+ case WebInputEvent::KeyUp:
+ np_event->what = keyUp;
+ return true;
+ default:
+ NOTREACHED();
+ return false;
+ }
+}
+
+static bool NPEventFromWebInputEvent(const WebInputEvent& event,
+ NPEvent* np_event) {
+ switch (event.type) {
+ case WebInputEvent::MouseMove:
+ case WebInputEvent::MouseLeave:
+ case WebInputEvent::MouseEnter:
+ case WebInputEvent::MouseDown:
+ case WebInputEvent::MouseUp:
+ if (event.size < sizeof(WebMouseEvent)) {
+ NOTREACHED();
+ return false;
+ }
+ return NPEventFromWebMouseEvent(*static_cast<const WebMouseEvent*>(&event), np_event);
+ case WebInputEvent::KeyDown:
+ case WebInputEvent::KeyUp:
+ if (event.size < sizeof(WebKeyboardEvent)) {
+ NOTREACHED();
+ return false;
+ }
+ return NPEventFromWebKeyboardEvent(*static_cast<const WebKeyboardEvent*>(&event), np_event);
+ default:
+ DLOG(WARNING) << "unknown event type" << event.type;
+ return false;
+ }
}
bool WebPluginDelegateImpl::HandleInputEvent(const WebInputEvent& event,
WebCursorInfo* cursor) {
DCHECK(windowless_) << "events should only be received in windowless mode";
DCHECK(cursor != NULL);
- // TODO: convert event into a NPEvent, and call NPP_HandleEvent(np_event).
- return true;
+ NPEvent np_event = {0};
+ if (!NPEventFromWebInputEvent(event, &np_event)) {
+ return false;
+ }
+ np_event.when = TickCount();
+ bool ret = instance()->NPP_HandleEvent(&np_event) != 0;
+ return ret;
}
WebPluginResourceClient* WebPluginDelegateImpl::CreateResourceClient(