summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--third_party/npapi/bindings/npapi.h7
-rw-r--r--webkit/glue/SConscript1
-rw-r--r--webkit/glue/plugins/plugin_host.cc24
-rw-r--r--webkit/glue/plugins/webplugin_delegate_impl.h40
-rw-r--r--webkit/glue/plugins/webplugin_delegate_impl_gtk.cc585
-rw-r--r--webkit/glue/webplugin_delegate.h14
-rw-r--r--webkit/glue/webplugin_impl.cc11
-rw-r--r--webkit/tools/test_shell/test_webview_delegate_gtk.cc17
8 files changed, 686 insertions, 13 deletions
diff --git a/third_party/npapi/bindings/npapi.h b/third_party/npapi/bindings/npapi.h
index 954a0ed..1ab6463 100644
--- a/third_party/npapi/bindings/npapi.h
+++ b/third_party/npapi/bindings/npapi.h
@@ -103,6 +103,13 @@
# endif /* XP_WIN */
#endif /* _WINDOWS */
+// BEGIN GOOGLE MODIFICATIONS
+// On Linux, be sure to set the Mozilla-specific flag.
+#ifdef OS_LINUX
+#define XP_UNIX 1
+#endif
+// END GOOGLE MODIFICATIONS
+
#ifdef __MWERKS__
# define _declspec __declspec
# ifdef __INTEL__
diff --git a/webkit/glue/SConscript b/webkit/glue/SConscript
index 025c67b..e9e818a 100644
--- a/webkit/glue/SConscript
+++ b/webkit/glue/SConscript
@@ -107,6 +107,7 @@ elif env.Bit('linux'):
input_files.extend([
'plugins/plugin_lib_linux.cc',
'plugins/plugin_list_linux.cc',
+ 'plugins/webplugin_delegate_impl_gtk.cc',
'webcursor_gtk.cc',
'webinputevent_linux.cc',
'webkit_glue_gtk.cc',
diff --git a/webkit/glue/plugins/plugin_host.cc b/webkit/glue/plugins/plugin_host.cc
index c12ee5c..8afa505 100644
--- a/webkit/glue/plugins/plugin_host.cc
+++ b/webkit/glue/plugins/plugin_host.cc
@@ -2,6 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// HACK: we need this #define in place before npapi.h is included for
+// plugins to work. However, all sorts of headers include npapi.h, so
+// the only way to be certain the define is in place is to put it
+// here. You might ask, "Why not set it in npapi.h directly, or in
+// this directory's SConscript, then?" but it turns out this define
+// makes npapi.h include Xlib.h, which in turn defines a ton of symbols
+// like None and Status, causing conflicts with the aforementioned
+// many headers that include npapi.h. Ugh.
+// See also webplugin_delegate_impl.cc.
+#define MOZ_X11 1
+
#include "config.h"
#include "webkit/glue/plugins/plugin_host.h"
@@ -743,6 +754,19 @@ NPError NPN_GetValue(NPP id, NPNVariable variable, void *value) {
rv = NPERR_NO_ERROR;
break;
}
+#if defined(OS_LINUX)
+ case NPNVToolkit:
+ // Tell them we are GTK2. (The alternative is GTK 1.2.)
+ *reinterpret_cast<int*>(value) = NPNVGtk2;
+ rv = NPERR_NO_ERROR;
+ break;
+
+ case NPNVSupportsXEmbedBool:
+ // Yes, we support XEmbed.
+ *reinterpret_cast<NPBool*>(value) = TRUE;
+ rv = NPERR_NO_ERROR;
+ break;
+#endif
case NPNVSupportsWindowless:
{
NPBool* supports_windowless = reinterpret_cast<NPBool*>(value);
diff --git a/webkit/glue/plugins/webplugin_delegate_impl.h b/webkit/glue/plugins/webplugin_delegate_impl.h
index fcb849d..61ee33c 100644
--- a/webkit/glue/plugins/webplugin_delegate_impl.h
+++ b/webkit/glue/plugins/webplugin_delegate_impl.h
@@ -5,6 +5,8 @@
#ifndef WEBKIT_GLUE_PLUGIN_WEBPLUGIN_DELEGATE_IMPL_H__
#define WEBKIT_GLUE_PLUGIN_WEBPLUGIN_DELEGATE_IMPL_H__
+#include "build/build_config.h"
+
#include <string>
#include <list>
@@ -27,12 +29,14 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
static WebPluginDelegateImpl* Create(const FilePath& filename,
const std::string& mime_type,
gfx::NativeView containing_view);
+#if defined(OS_WIN)
static bool IsPluginDelegateWindow(HWND window);
static bool GetPluginNameFromWindow(HWND window, std::wstring *plugin_name);
// Returns true if the window handle passed in is that of the dummy
// activation window for windowless plugins.
static bool IsDummyActivationWindow(HWND window);
+#endif // OS_WIN)
// WebPluginDelegate implementation
virtual void PluginDestroyed();
@@ -44,8 +48,14 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
bool load_manually);
virtual void UpdateGeometry(const gfx::Rect& window_rect,
const gfx::Rect& clip_rect);
+#if defined(OS_WIN)
virtual void Paint(HDC hdc, const gfx::Rect& rect);
virtual void Print(HDC hdc);
+#else
+ // TODO(port): temporary workaround.
+ virtual void Paint(void* dc, const gfx::Rect& rect);
+ virtual void Print(void* dc);
+#endif
virtual void SetFocus(); // only called when windowless
// only called when windowless
virtual bool HandleEvent(NPEvent* event,
@@ -82,6 +92,7 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
gfx::Rect rect() const { return window_rect_; }
gfx::Rect clip_rect() const { return clip_rect_; }
+#if defined(OS_WIN)
enum PluginQuirks {
PLUGIN_QUIRK_SETWINDOW_TWICE = 1,
PLUGIN_QUIRK_THROTTLE_WM_USER_PLUS_ONE = 2,
@@ -93,6 +104,7 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
PLUGIN_QUIRK_PATCH_SETCURSOR = 128,
PLUGIN_QUIRK_BLOCK_NONSTANDARD_GETURL_REQUESTS = 256,
};
+#endif
int quirks() { return quirks_; }
@@ -122,6 +134,7 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
// See NPAPI NPP_SetWindow for more information.
void WindowedSetWindow();
+#if defined(OS_WIN)
// Registers the window class for our window
ATOM RegisterNativeWindowClass();
@@ -138,12 +151,18 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
static void OnThrottleMessage();
static void ThrottleMessage(WNDPROC proc, HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam);
+#endif
//----------------------------
// used for windowless plugins
void WindowlessUpdateGeometry(const gfx::Rect& window_rect,
const gfx::Rect& clip_rect);
+#if defined(OS_WIN)
void WindowlessPaint(HDC hdc, const gfx::Rect& rect);
+#else
+ // TODO(port): implement.
+ void WindowlessPaint(void* dc, const gfx::Rect& rect);
+#endif
// Tells the plugin about the current state of the window.
// See NPAPI NPP_SetWindow for more information.
@@ -159,15 +178,19 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
void DestroyInstance();
// used for windowed plugins
- HWND windowed_handle_;
+ gfx::NativeView windowed_handle_;
+#if defined(OS_WIN)
bool windowed_did_set_window_;
gfx::Rect windowed_last_pos_;
+#endif
+#if defined(OS_WIN)
// this is an optimization to avoid calling SetWindow to the plugin
// when it is not necessary. Initially, we need to call SetWindow,
// and after that we only need to call it when the geometry changes.
// use this flag to indicate whether we really need it or not.
bool windowless_needs_set_window_;
+#endif
// used by windowed and windowless plugins
bool windowless_;
@@ -175,20 +198,23 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
WebPlugin* plugin_;
scoped_refptr<NPAPI::PluginInstance> instance_;
+#if defined(OS_WIN)
// Original wndproc before we subclassed.
WNDPROC plugin_wnd_proc_;
// Used to throttle WM_USER+1 messages in Flash.
uint32 last_message_;
bool is_calling_wndproc;
+#endif // OS_WIN
- HWND parent_;
+ gfx::NativeView parent_;
NPWindow window_;
gfx::Rect window_rect_;
gfx::Rect clip_rect_;
std::vector<gfx::Rect> cutout_rects_;
int quirks_;
+#if defined(OS_WIN)
// Windowless plugins don't have keyboard focus causing issues with the
// plugin not receiving keyboard events if the plugin enters a modal
// loop like TrackPopupMenuEx or MessageBox, etc.
@@ -210,7 +236,7 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
// a plugin in the course of a NPP_HandleEvent call.
static LRESULT CALLBACK HandleEventMessageFilterHook(int code, WPARAM wParam,
LPARAM lParam);
-
+#endif
// Called by the message filter hook when the plugin enters a modal loop.
void OnModalLoopEntered();
@@ -220,6 +246,10 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
// Indicates the end of a user gesture period.
void OnUserGestureEnd();
+ // The url with which the plugin was instantiated.
+ std::string plugin_url_;
+
+#if defined(OS_WIN)
// Handle to the message filter hook
HHOOK handle_event_message_filter_hook_;
@@ -237,9 +267,6 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
// asynchronously.
ScopedRunnableMethodFactory<WebPluginDelegateImpl> user_gesture_msg_factory_;
- // The url with which the plugin was instantiated.
- std::string plugin_url_;
-
// The plugin module handle.
HMODULE plugin_module_handle_;
@@ -254,6 +281,7 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
// Holds the current cursor set by the windowless plugin.
WebCursor current_windowless_cursor_;
+#endif
DISALLOW_EVIL_CONSTRUCTORS(WebPluginDelegateImpl);
};
diff --git a/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc b/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc
new file mode 100644
index 0000000..9e98e01
--- /dev/null
+++ b/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc
@@ -0,0 +1,585 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// HACK: we need this #define in place before npapi.h is included for
+// plugins to work. However, all sorts of headers include npapi.h, so
+// the only way to be certain the define is in place is to put it
+// here. You might ask, "Why not set it in npapi.h directly, or in
+// this directory's SConscript, then?" but it turns out this define
+// makes npapi.h include Xlib.h, which in turn defines a ton of symbols
+// like None and Status, causing conflicts with the aforementioned
+// many headers that include npapi.h. Ugh.
+// See also plugin_host.cc.
+#define MOZ_X11 1
+
+#include "webkit/glue/plugins/webplugin_delegate_impl.h"
+
+#include <string>
+#include <vector>
+
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+
+#include "base/file_util.h"
+#include "base/message_loop.h"
+#include "base/process_util.h"
+#include "base/stats_counters.h"
+#include "base/string_util.h"
+// #include "webkit/default_plugin/plugin_impl.h"
+#include "webkit/glue/glue_util.h"
+#include "webkit/glue/webplugin.h"
+#include "webkit/glue/plugins/plugin_constants_win.h"
+#include "webkit/glue/plugins/plugin_instance.h"
+#include "webkit/glue/plugins/plugin_lib.h"
+#include "webkit/glue/plugins/plugin_list.h"
+#include "webkit/glue/plugins/plugin_stream_url.h"
+#include "webkit/glue/webkit_glue.h"
+
+WebPluginDelegateImpl* WebPluginDelegateImpl::Create(
+ const FilePath& filename,
+ const std::string& mime_type,
+ gfx::NativeView containing_view) {
+ scoped_refptr<NPAPI::PluginLib> plugin =
+ NPAPI::PluginLib::CreatePluginLib(filename);
+ if (plugin.get() == NULL)
+ return NULL;
+
+ NPError err = plugin->NP_Initialize();
+ if (err != NPERR_NO_ERROR)
+ return NULL;
+
+ scoped_refptr<NPAPI::PluginInstance> instance =
+ plugin->CreateInstance(mime_type);
+ return new WebPluginDelegateImpl(containing_view, instance.get());
+}
+
+WebPluginDelegateImpl::WebPluginDelegateImpl(
+ gfx::NativeView containing_view,
+ NPAPI::PluginInstance *instance)
+ :
+ windowed_handle_(0),
+ windowless_(false),
+ plugin_(NULL),
+ instance_(instance),
+ parent_(containing_view),
+ quirks_(0)
+ {
+ memset(&window_, 0, sizeof(window_));
+
+}
+
+WebPluginDelegateImpl::~WebPluginDelegateImpl() {
+ DestroyInstance();
+
+ if (!windowless_)
+ WindowedDestroyWindow();
+}
+
+void WebPluginDelegateImpl::PluginDestroyed() {
+ delete this;
+}
+
+bool WebPluginDelegateImpl::Initialize(const GURL& url,
+ char** argn,
+ char** argv,
+ int argc,
+ WebPlugin* plugin,
+ bool load_manually) {
+ plugin_ = plugin;
+
+ instance_->set_web_plugin(plugin);
+ NPAPI::PluginInstance* old_instance =
+ NPAPI::PluginInstance::SetInitializingInstance(instance_);
+
+ bool start_result = instance_->Start(url, argn, argv, argc, load_manually);
+
+ NPAPI::PluginInstance::SetInitializingInstance(old_instance);
+
+ 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.
+ NOTIMPLEMENTED() << "windowless not implemented";
+ return false;
+ // instance_->set_window_handle(parent_);
+ // CreateDummyWindowForActivation();
+ // handle_event_pump_messages_event_ = CreateEvent(NULL, TRUE, FALSE, NULL);
+ } else {
+ if (!WindowedCreatePlugin())
+ return false;
+ }
+
+ plugin->SetWindow(windowed_handle_, /* unused event param */ NULL);
+ plugin_url_ = url.spec();
+
+ return true;
+}
+
+void WebPluginDelegateImpl::DestroyInstance() {
+ if (instance_ && (instance_->npp()->ndata != NULL)) {
+ // Shutdown all streams before destroying so that
+ // no streams are left "in progress". Need to do
+ // this before calling set_web_plugin(NULL) because the
+ // instance uses the helper to do the download.
+ instance_->CloseStreams();
+
+ window_.window = NULL;
+ // if (!(quirks_ & PLUGIN_QUIRK_DONT_SET_NULL_WINDOW_HANDLE_ON_DESTROY)) {
+ instance_->NPP_SetWindow(&window_);
+ // }
+
+ instance_->NPP_Destroy();
+
+ instance_->set_web_plugin(NULL);
+
+ instance_ = 0;
+ }
+}
+
+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);
+ }
+}
+
+void WebPluginDelegateImpl::Paint(void* dc, const gfx::Rect& rect) {
+ if (windowless_) {
+ // TODO(port): windowless painting.
+ // WindowlessPaint(dc, rect);
+ }
+}
+
+void WebPluginDelegateImpl::Print(void* dc) {
+ NOTIMPLEMENTED();
+}
+
+NPObject* WebPluginDelegateImpl::GetPluginScriptableObject() {
+ return instance_->GetPluginScriptableObject();
+}
+
+void WebPluginDelegateImpl::DidFinishLoadWithReason(NPReason reason) {
+ instance()->DidFinishLoadWithReason(reason);
+}
+
+int WebPluginDelegateImpl::GetProcessId() {
+ // We are in process, so the plugin pid is this current process pid.
+ return base::GetCurrentProcId();
+}
+
+void WebPluginDelegateImpl::SendJavaScriptStream(const std::string& url,
+ const std::wstring& result,
+ bool success,
+ bool notify_needed,
+ int notify_data) {
+ instance()->SendJavaScriptStream(url, result, success, notify_needed,
+ notify_data);
+}
+
+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.
+ // XXX DCHECK(windowed_did_set_window_);
+ }
+
+ instance()->DidReceiveManualResponse(url, mime_type, headers,
+ expected_length, last_modified);
+}
+
+void WebPluginDelegateImpl::DidReceiveManualData(const char* buffer,
+ int length) {
+ instance()->DidReceiveManualData(buffer, length);
+}
+
+void WebPluginDelegateImpl::DidFinishManualLoading() {
+ instance()->DidFinishManualLoading();
+}
+
+void WebPluginDelegateImpl::DidManualLoadFail() {
+ instance()->DidManualLoadFail();
+}
+
+FilePath WebPluginDelegateImpl::GetPluginPath() {
+ return instance()->plugin_lib()->plugin_info().path;
+}
+
+void WebPluginDelegateImpl::InstallMissingPlugin() {
+ /* XXX NPEvent evt;
+ evt.event = PluginInstallerImpl::kInstallMissingPluginMessage;
+ evt.lParam = 0;
+ evt.wParam = 0;
+ instance()->NPP_HandleEvent(&evt); */
+}
+
+void WebPluginDelegateImpl::WindowedUpdateGeometry(
+ const gfx::Rect& window_rect,
+ const gfx::Rect& clip_rect) {
+ if (WindowedReposition(window_rect, clip_rect) ||
+ false) { // !windowed_did_set_window_) {
+ // Let the plugin know that it has been moved
+ WindowedSetWindow();
+ }
+}
+
+bool WebPluginDelegateImpl::WindowedCreatePlugin() {
+ DCHECK(!windowed_handle_);
+
+ bool xembed;
+ NPError err = instance_->NPP_GetValue(NPPVpluginNeedsXEmbed, &xembed);
+ DCHECK(err == NPERR_NO_ERROR);
+ if (!xembed) {
+ NOTIMPLEMENTED() << "Windowed plugin but without xembed.";
+ return false;
+ }
+
+ windowed_handle_ = gtk_socket_new();
+ gtk_widget_set_parent(windowed_handle_, parent_);
+ // TODO(evanm): connect to signals on the socket, like when the other side
+ // goes away.
+
+ window_.window = GINT_TO_POINTER(
+ gtk_socket_get_id(GTK_SOCKET(windowed_handle_)));
+ gtk_widget_show(windowed_handle_);
+
+ NPSetWindowCallbackStruct* extra = new NPSetWindowCallbackStruct;
+ extra->display = GDK_WINDOW_XDISPLAY(windowed_handle_->window);
+ GdkVisual* visual = gdk_drawable_get_visual(windowed_handle_->window);
+ extra->visual = GDK_VISUAL_XVISUAL(visual);
+ extra->depth = visual->depth;
+ extra->colormap = GDK_COLORMAP_XCOLORMAP(gdk_drawable_get_colormap(windowed_handle_->window));
+ window_.ws_info = extra;
+
+ return true;
+}
+
+void WebPluginDelegateImpl::WindowedDestroyWindow() {
+#if 0
+ if (windowed_handle_ != NULL) {
+ // Unsubclass the window.
+ WNDPROC current_wnd_proc = reinterpret_cast<WNDPROC>(
+ GetWindowLongPtr(windowed_handle_, GWLP_WNDPROC));
+ if (current_wnd_proc == NativeWndProc) {
+ SetWindowLongPtr(windowed_handle_,
+ GWLP_WNDPROC,
+ reinterpret_cast<LONG>(plugin_wnd_proc_));
+ }
+
+ DestroyWindow(windowed_handle_);
+ windowed_handle_ = 0;
+ }
+#endif
+}
+
+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()) {
+ gdk_window_resize(windowed_handle_->window,
+ window_rect.width(),
+ window_rect.height());
+ }
+
+ GtkAllocation allocation = { window_rect_.x(), window_rect_.y(),
+ window_rect_.width(), window_rect_.height() };
+ gtk_widget_size_allocate(windowed_handle_, &allocation);
+
+ window_rect_ = window_rect;
+ clip_rect_ = clip_rect;
+
+ // Ensure that the entire window gets repainted.
+ gtk_widget_queue_draw(windowed_handle_);
+
+ return true;
+}
+
+void WebPluginDelegateImpl::WindowedSetWindow() {
+ if (!instance_)
+ return;
+
+ if (!windowed_handle_) {
+ NOTREACHED();
+ return;
+ }
+
+ // XXX 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();
+
+ //window_.window = windowed_handle_;
+ window_.type = NPWindowTypeWindow;
+
+ // Reset this flag before entering the instance in case of side-effects.
+ // XXX windowed_did_set_window_ = true;
+
+ NPError err = instance()->NPP_SetWindow(&window_);
+ DCHECK(err == NPERR_NO_ERROR);
+#if 0
+ if (quirks_ & PLUGIN_QUIRK_SETWINDOW_TWICE)
+ instance()->NPP_SetWindow(&window_);
+
+ WNDPROC current_wnd_proc = reinterpret_cast<WNDPROC>(
+ GetWindowLongPtr(windowed_handle_, GWLP_WNDPROC));
+ if (current_wnd_proc != NativeWndProc) {
+ plugin_wnd_proc_ = reinterpret_cast<WNDPROC>(SetWindowLongPtr(
+ windowed_handle_, GWLP_WNDPROC, reinterpret_cast<LONG>(NativeWndProc)));
+ }
+#endif
+}
+
+void WebPluginDelegateImpl::WindowlessUpdateGeometry(
+ const gfx::Rect& window_rect,
+ const gfx::Rect& clip_rect) {
+ // Only resend to the instance if the geometry has changed.
+ if (window_rect == window_rect_ && clip_rect == clip_rect_)
+ return;
+ /*
+ // Set this flag before entering the instance in case of side-effects.
+ windowless_needs_set_window_ = true;
+
+ // We will inform the instance of this change when we call NPP_SetWindow.
+ clip_rect_ = clip_rect;
+ cutout_rects_.clear();
+
+ if (window_rect_ != window_rect) {
+ window_rect_ = window_rect;
+
+ WindowlessSetWindow(true);
+
+ WINDOWPOS win_pos = {0};
+ win_pos.x = window_rect_.x();
+ win_pos.y = window_rect_.y();
+ win_pos.cx = window_rect_.width();
+ win_pos.cy = window_rect_.height();
+
+ NPEvent pos_changed_event;
+ pos_changed_event.event = WM_WINDOWPOSCHANGED;
+ pos_changed_event.wParam = 0;
+ pos_changed_event.lParam = PtrToUlong(&win_pos);
+
+ instance()->NPP_HandleEvent(&pos_changed_event);
+ }
+ */
+}
+
+#if 0
+void WebPluginDelegateImpl::WindowlessPaint(HDC hdc,
+ const gfx::Rect& damage_rect) {
+ DCHECK(hdc);
+
+ RECT damage_rect_win;
+ damage_rect_win.left = damage_rect.x(); // + window_rect_.x();
+ damage_rect_win.top = damage_rect.y(); // + window_rect_.y();
+ damage_rect_win.right = damage_rect_win.left + damage_rect.width();
+ damage_rect_win.bottom = damage_rect_win.top + damage_rect.height();
+
+ // We need to pass the HDC to the plugin via NPP_SetWindow in the
+ // first paint to ensure that it initiates rect invalidations.
+ if (window_.window == NULL)
+ windowless_needs_set_window_ = true;
+
+ window_.window = hdc;
+ // TODO(darin): we should avoid calling NPP_SetWindow here since it may
+ // cause page layout to be invalidated.
+
+ // We really don't need to continually call SetWindow.
+ // m_needsSetWindow flags when the geometry has changed.
+ if (windowless_needs_set_window_)
+ WindowlessSetWindow(false);
+
+ NPEvent paint_event;
+ paint_event.event = WM_PAINT;
+ // NOTE: NPAPI is not 64bit safe. It puts pointers into 32bit values.
+ paint_event.wParam = PtrToUlong(hdc);
+ paint_event.lParam = PtrToUlong(&damage_rect_win);
+ static StatsRate plugin_paint("Plugin.Paint");
+ StatsScope<StatsRate> scope(plugin_paint);
+ instance()->NPP_HandleEvent(&paint_event);
+}
+#endif
+
+void WebPluginDelegateImpl::WindowlessSetWindow(bool force_set_window) {
+ if (!instance())
+ return;
+
+ 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();
+ 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;
+
+ NPError err = instance()->NPP_SetWindow(&window_);
+ DCHECK(err == NPERR_NO_ERROR);
+}
+
+void WebPluginDelegateImpl::SetFocus() {
+ DCHECK(instance()->windowless());
+
+ NOTIMPLEMENTED();
+ /* NPEvent focus_event;
+ focus_event.event = WM_SETFOCUS;
+ focus_event.wParam = 0;
+ focus_event.lParam = 0;
+
+ instance()->NPP_HandleEvent(&focus_event);*/
+}
+
+bool WebPluginDelegateImpl::HandleEvent(NPEvent* event,
+ WebCursor* cursor) {
+ NOTIMPLEMENTED();
+#if 0
+ DCHECK(windowless_) << "events should only be received in windowless mode";
+ DCHECK(cursor != NULL);
+
+ // To ensure that the plugin receives keyboard events we set focus to the
+ // dummy window.
+ // TODO(iyengar) We need a framework in the renderer to identify which
+ // windowless plugin is under the mouse and to handle this. This would
+ // also require some changes in RenderWidgetHost to detect this in the
+ // WM_MOUSEACTIVATE handler and inform the renderer accordingly.
+ HWND prev_focus_window = NULL;
+ if (event->event == WM_RBUTTONDOWN) {
+ prev_focus_window = ::SetFocus(dummy_window_for_activation_);
+ }
+
+ if (ShouldTrackEventForModalLoops(event)) {
+ // A windowless plugin can enter a modal loop in a NPP_HandleEvent call.
+ // For e.g. Flash puts up a context menu when we right click on the
+ // windowless plugin area. We detect this by setting up a message filter
+ // hook pror to calling NPP_HandleEvent on the plugin and unhook on
+ // return from NPP_HandleEvent. If the plugin does enter a modal loop
+ // in that context we unhook on receiving the first notification in
+ // the message filter hook.
+ handle_event_message_filter_hook_ =
+ SetWindowsHookEx(WH_MSGFILTER, HandleEventMessageFilterHook, NULL,
+ GetCurrentThreadId());
+ }
+
+ bool old_task_reentrancy_state =
+ MessageLoop::current()->NestableTasksAllowed();
+
+ current_plugin_instance_ = this;
+
+ handle_event_depth_++;
+
+ bool pop_user_gesture = false;
+
+ if (IsUserGestureMessage(event->event)) {
+ pop_user_gesture = true;
+ instance()->PushPopupsEnabledState(true);
+ }
+
+ bool ret = instance()->NPP_HandleEvent(event) != 0;
+
+ if (event->event == WM_MOUSEMOVE) {
+ // Snag a reference to the current cursor ASAP in case the plugin modified
+ // it. There is a nasty race condition here with the multiprocess browser
+ // as someone might be setting the cursor in the main process as well.
+ *cursor = current_windowless_cursor_;
+ }
+
+ if (pop_user_gesture) {
+ instance()->PopPopupsEnabledState();
+ }
+
+ handle_event_depth_--;
+
+ current_plugin_instance_ = NULL;
+
+ MessageLoop::current()->SetNestableTasksAllowed(old_task_reentrancy_state);
+
+ if (handle_event_message_filter_hook_) {
+ UnhookWindowsHookEx(handle_event_message_filter_hook_);
+ handle_event_message_filter_hook_ = NULL;
+ }
+
+ // We could have multiple NPP_HandleEvent calls nested together in case
+ // the plugin enters a modal loop. Reset the pump messages event when
+ // the outermost NPP_HandleEvent call unwinds.
+ if (handle_event_depth_ == 0) {
+ ResetEvent(handle_event_pump_messages_event_);
+ }
+
+ if (event->event == WM_RBUTTONUP && ::IsWindow(prev_focus_window)) {
+ ::SetFocus(prev_focus_window);
+ }
+
+ return ret;
+#endif
+ return 0;
+}
+
+WebPluginResourceClient* WebPluginDelegateImpl::CreateResourceClient(
+ int resource_id, const std::string &url, bool notify_needed,
+ void *notify_data, void* existing_stream) {
+ // Stream already exists. This typically happens for range requests
+ // initiated via NPN_RequestRead.
+ if (existing_stream) {
+ NPAPI::PluginStream* plugin_stream =
+ reinterpret_cast<NPAPI::PluginStream*>(existing_stream);
+
+ plugin_stream->CancelRequest();
+
+ return plugin_stream->AsResourceClient();
+ }
+
+ if (notify_needed) {
+ instance()->SetURLLoadData(GURL(url.c_str()), notify_data);
+ }
+ std::string mime_type;
+ NPAPI::PluginStreamUrl *stream = instance()->CreateStream(resource_id,
+ url,
+ mime_type,
+ notify_needed,
+ notify_data);
+ return stream;
+}
+
+void WebPluginDelegateImpl::URLRequestRouted(const std::string&url,
+ bool notify_needed,
+ void* notify_data) {
+ if (notify_needed) {
+ instance()->SetURLLoadData(GURL(url.c_str()), notify_data);
+ }
+}
+
+
diff --git a/webkit/glue/webplugin_delegate.h b/webkit/glue/webplugin_delegate.h
index 16d9c50..4581a829 100644
--- a/webkit/glue/webplugin_delegate.h
+++ b/webkit/glue/webplugin_delegate.h
@@ -12,8 +12,10 @@
#include "base/file_path.h"
#include "base/gfx/native_widget_types.h"
#include "base/gfx/rect.h"
+#include "build/build_config.h"
#include "third_party/npapi/bindings/npapi.h"
+// TODO(port): put in OS_WIN check.
typedef struct HDC__* HDC;
struct NPObject;
@@ -53,12 +55,24 @@ class WebPluginDelegate {
virtual void UpdateGeometry(const gfx::Rect& window_rect,
const gfx::Rect& clip_rect) = 0;
+#if defined(OS_WIN)
// Tells the plugin to paint the damaged rect. The HDC is only used for
// windowless plugins.
virtual void Paint(HDC hdc, const gfx::Rect& rect) = 0;
// Tells the plugin to print itself.
virtual void Print(HDC hdc) = 0;
+#else
+ // TODO(port): these are not intended to be implementable for now,
+ // and will have the prototypes fixed once they are implemented.
+
+ // Tells the plugin to paint the damaged rect. The HDC is only used for
+ // windowless plugins.
+ virtual void Paint(void* dc, const gfx::Rect& rect) = 0;
+
+ // Tells the plugin to print itself.
+ virtual void Print(void* dc) = 0;
+#endif
// Informs the plugin that it now has focus.
virtual void SetFocus() = 0;
diff --git a/webkit/glue/webplugin_impl.cc b/webkit/glue/webplugin_impl.cc
index deb2ff9..2ebe5f5 100644
--- a/webkit/glue/webplugin_impl.cc
+++ b/webkit/glue/webplugin_impl.cc
@@ -702,19 +702,20 @@ void WebPluginImpl::paint(WebCore::GraphicsContext* gc,
static_cast<float>(origin.y()));
#if defined(OS_WIN)
- // HDC is only used when in windowless mode.
- HDC hdc = gc->platformContext()->canvas()->beginPlatformPaint();
+ // Note that HDC is only used when in windowless mode.
+ HDC dc = gc->platformContext()->canvas()->beginPlatformPaint();
#else
- NOTIMPLEMENTED();
+ // TODO(port): the equivalent of the above.
+ void* dc = NULL; // Temporary, to reduce ifdefs.
#endif
WebCore::IntRect window_rect =
WebCore::IntRect(view->contentsToWindow(damage_rect.location()),
damage_rect.size());
-#if defined(OS_WIN)
- delegate_->Paint(hdc, webkit_glue::FromIntRect(window_rect));
+ delegate_->Paint(dc, webkit_glue::FromIntRect(window_rect));
+#if defined(OS_WIN)
gc->platformContext()->canvas()->endPlatformPaint();
#endif
gc->restore();
diff --git a/webkit/tools/test_shell/test_webview_delegate_gtk.cc b/webkit/tools/test_shell/test_webview_delegate_gtk.cc
index 831691a..8482080 100644
--- a/webkit/tools/test_shell/test_webview_delegate_gtk.cc
+++ b/webkit/tools/test_shell/test_webview_delegate_gtk.cc
@@ -22,7 +22,9 @@
#include "webkit/glue/weburlrequest.h"
#include "webkit/glue/webkit_glue.h"
#include "webkit/glue/webview.h"
+#include "webkit/glue/plugins/plugin_list.h"
#include "webkit/glue/window_open_disposition.h"
+#include "webkit/glue/plugins/webplugin_delegate_impl.h"
#include "webkit/tools/test_shell/test_navigation_controller.h"
#include "webkit/tools/test_shell/test_shell.h"
@@ -77,8 +79,19 @@ WebPluginDelegate* TestWebViewDelegate::CreatePluginDelegate(
const std::string& mime_type,
const std::string& clsid,
std::string* actual_mime_type) {
- NOTIMPLEMENTED();
- return NULL;
+ bool allow_wildcard = true;
+ WebPluginInfo info;
+ if (!NPAPI::PluginList::Singleton()->GetPluginInfo(url, mime_type, clsid,
+ allow_wildcard, &info,
+ actual_mime_type))
+ return NULL;
+
+ if (actual_mime_type && !actual_mime_type->empty())
+ return WebPluginDelegateImpl::Create(info.path, *actual_mime_type,
+ shell_->webViewHost()->view_handle());
+ else
+ return WebPluginDelegateImpl::Create(info.path, mime_type,
+ shell_->webViewHost()->view_handle());
}
void TestWebViewDelegate::ShowJavaScriptAlert(const std::wstring& message) {