summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpiman@chromium.org <piman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-25 20:50:32 +0000
committerpiman@chromium.org <piman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-25 20:50:32 +0000
commitc0478b0985b9893601125a88a32a648656a75948 (patch)
tree8af9f0dcb303cbcdbf0da4c134f025d4e7ddd238
parentd4eb7120deddccf96ff85ecc393b0757497bb7d6 (diff)
downloadchromium_src-c0478b0985b9893601125a88a32a648656a75948.zip
chromium_src-c0478b0985b9893601125a88a32a648656a75948.tar.gz
chromium_src-c0478b0985b9893601125a88a32a648656a75948.tar.bz2
linux: new socket/plug code for windowed plugins
This CL reworks the GtkSocket/GtkPlug code for windowed plugins on linux. Instead of having the plugin ask the browser to create a socket to plug into, it simply creates a plug and sends it to the browser. The browser creates a socket and attaches the plug when the socket becomes realized This fixes 2 main issues: - we can create windowed plugins in background tabs (Issue 16125) - we can detach tabs with windowed plugins and reattach them (Issue 17110) I reworked the IPCs, so it removes some amount of linux-specific things. We also need less synchronous IPCs to create/destroy plugins, so that should be a bit faster. In particular, I removed the plugin pid map, and instead made sure the renderer always destroys the plugin containers if the plugin process crashes - they will be destroyed if the renderer process crashes. Let me know if you have an issue with that. Also, the intermediate plug/socket creation now happens in webplugin_delegate_impl_gtk. That means test_shell uses it as well. It made the code a lot simpler, and means we're testing it as well, albeit with a bit of extra overhead. Bonus: I found a big bad bug in the GtkPluginContainer that made its width/height alias with some internal gtk structures. That was certainly causing some amounts of bugs. Bonus 2: scrolling now looks more in sync with the rest of the page, though I'm not exactly sure which part caused that. BUG=16125,17110 TEST=a lot of manual testing involving YouTube videos Review URL: http://codereview.chromium.org/174295 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@24309 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/renderer_host/render_view_host.cc2
-rw-r--r--chrome/browser/renderer_host/render_widget_host.cc11
-rw-r--r--chrome/browser/renderer_host/render_widget_host.h5
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view.h7
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_gtk.cc29
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_gtk.h11
-rw-r--r--chrome/browser/renderer_host/test/test_render_view_host.h6
-rw-r--r--chrome/common/plugin_messages_internal.h9
-rw-r--r--chrome/common/render_messages_internal.h14
-rw-r--r--chrome/plugin/webplugin_proxy.cc52
-rw-r--r--chrome/plugin/webplugin_proxy.h11
-rw-r--r--chrome/renderer/render_view.cc11
-rw-r--r--chrome/renderer/render_view.h1
-rw-r--r--chrome/renderer/webplugin_delegate_proxy.cc29
-rw-r--r--chrome/renderer/webplugin_delegate_proxy.h9
-rw-r--r--webkit/glue/plugins/gtk_plugin_container.cc2
-rw-r--r--webkit/glue/plugins/gtk_plugin_container_manager.cc105
-rw-r--r--webkit/glue/plugins/gtk_plugin_container_manager.h21
-rw-r--r--webkit/glue/plugins/webplugin_delegate_impl.h7
-rw-r--r--webkit/glue/plugins/webplugin_delegate_impl_gtk.cc35
-rw-r--r--webkit/glue/webplugin.h10
-rw-r--r--webkit/glue/webplugin_impl.cc14
-rw-r--r--webkit/glue/webplugin_impl.h3
-rw-r--r--webkit/glue/webview_delegate.h6
-rw-r--r--webkit/tools/test_shell/test_webview_delegate.h4
-rw-r--r--webkit/tools/test_shell/test_webview_delegate_gtk.cc8
-rw-r--r--webkit/tools/test_shell/webview_host.h9
-rw-r--r--webkit/tools/test_shell/webview_host_gtk.cc6
28 files changed, 177 insertions, 260 deletions
diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc
index d028db5..422c313 100644
--- a/chrome/browser/renderer_host/render_view_host.cc
+++ b/chrome/browser/renderer_host/render_view_host.cc
@@ -1429,8 +1429,6 @@ void RenderViewHost::OnMissingPluginStatus(int status) {
void RenderViewHost::OnCrashedPlugin(base::ProcessId pid,
const FilePath& plugin_path) {
- view()->PluginProcessCrashed(pid);
-
RenderViewHostDelegate::BrowserIntegration* integration_delegate =
delegate_->GetBrowserIntegrationDelegate();
if (integration_delegate)
diff --git a/chrome/browser/renderer_host/render_widget_host.cc b/chrome/browser/renderer_host/render_widget_host.cc
index c7d7e19..40fba47 100644
--- a/chrome/browser/renderer_host/render_widget_host.cc
+++ b/chrome/browser/renderer_host/render_widget_host.cc
@@ -782,15 +782,12 @@ void RenderWidgetHost::OnMsgImeUpdateStatus(int control,
#if defined(OS_LINUX)
-void RenderWidgetHost::OnMsgCreatePluginContainer(
- base::ProcessId pid,
- gfx::PluginWindowHandle* container) {
- *container = view_->CreatePluginContainer(pid);
+void RenderWidgetHost::OnMsgCreatePluginContainer(gfx::PluginWindowHandle id) {
+ view_->CreatePluginContainer(id);
}
-void RenderWidgetHost::OnMsgDestroyPluginContainer(
- gfx::PluginWindowHandle container) {
- view_->DestroyPluginContainer(container);
+void RenderWidgetHost::OnMsgDestroyPluginContainer(gfx::PluginWindowHandle id) {
+ view_->DestroyPluginContainer(id);
}
#elif defined(OS_MACOSX)
diff --git a/chrome/browser/renderer_host/render_widget_host.h b/chrome/browser/renderer_host/render_widget_host.h
index 3b52e4a..242d56b 100644
--- a/chrome/browser/renderer_host/render_widget_host.h
+++ b/chrome/browser/renderer_host/render_widget_host.h
@@ -399,9 +399,8 @@ class RenderWidgetHost : public IPC::Channel::Listener,
// having to bring in render_messages.h in a header file.
void OnMsgImeUpdateStatus(int control, const gfx::Rect& caret_rect);
#if defined(OS_LINUX)
- void OnMsgCreatePluginContainer(base::ProcessId pid,
- gfx::PluginWindowHandle* container);
- void OnMsgDestroyPluginContainer(gfx::PluginWindowHandle container);
+ void OnMsgCreatePluginContainer(gfx::PluginWindowHandle id);
+ void OnMsgDestroyPluginContainer(gfx::PluginWindowHandle id);
#elif defined(OS_MACOSX)
void OnMsgShowPopup(const ViewHostMsg_ShowPopup_Params& params);
void OnMsgGetScreenInfo(gfx::NativeViewId view,
diff --git a/chrome/browser/renderer_host/render_widget_host_view.h b/chrome/browser/renderer_host/render_widget_host_view.h
index 31f1f64..b022f7e 100644
--- a/chrome/browser/renderer_host/render_widget_host_view.h
+++ b/chrome/browser/renderer_host/render_widget_host_view.h
@@ -161,13 +161,10 @@ class RenderWidgetHostView {
#endif
#if defined(OS_LINUX)
- virtual gfx::PluginWindowHandle CreatePluginContainer(
- base::ProcessId plugin_process_id) = 0;
- virtual void DestroyPluginContainer(gfx::PluginWindowHandle container) = 0;
+ virtual void CreatePluginContainer(gfx::PluginWindowHandle id) = 0;
+ virtual void DestroyPluginContainer(gfx::PluginWindowHandle id) = 0;
#endif
- virtual void PluginProcessCrashed(base::ProcessId pid) { }
-
void set_activatable(bool activatable) {
activatable_ = activatable;
}
diff --git a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc
index 48fed82..2353bb9 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc
+++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc
@@ -619,31 +619,12 @@ void RenderWidgetHostViewGtk::ReceivedSelectionText(GtkClipboard* clipboard,
UTF8ToUTF16(text)));
}
-gfx::PluginWindowHandle RenderWidgetHostViewGtk::CreatePluginContainer(
- base::ProcessId plugin_process_id) {
- gfx::PluginWindowHandle handle =
- plugin_container_manager_.CreatePluginContainer();
- plugin_pid_map_.insert(std::make_pair(plugin_process_id, handle));
- return handle;
+void RenderWidgetHostViewGtk::CreatePluginContainer(
+ gfx::PluginWindowHandle id) {
+ plugin_container_manager_.CreatePluginContainer(id);
}
void RenderWidgetHostViewGtk::DestroyPluginContainer(
- gfx::PluginWindowHandle container) {
- plugin_container_manager_.DestroyPluginContainer(container);
-
- for (PluginPidMap::iterator i = plugin_pid_map_.begin();
- i != plugin_pid_map_.end(); ++i) {
- if (i->second == container) {
- plugin_pid_map_.erase(i);
- break;
- }
- }
-}
-
-void RenderWidgetHostViewGtk::PluginProcessCrashed(base::ProcessId pid) {
- for (PluginPidMap::iterator i = plugin_pid_map_.find(pid);
- i != plugin_pid_map_.end() && i->first == pid; ++i) {
- plugin_container_manager_.DestroyPluginContainer(i->second);
- }
- plugin_pid_map_.erase(pid);
+ gfx::PluginWindowHandle id) {
+ plugin_container_manager_.DestroyPluginContainer(id);
}
diff --git a/chrome/browser/renderer_host/render_widget_host_view_gtk.h b/chrome/browser/renderer_host/render_widget_host_view_gtk.h
index 937e254..97ec6cf 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_gtk.h
+++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.h
@@ -64,10 +64,8 @@ class RenderWidgetHostViewGtk : public RenderWidgetHostView {
virtual void PasteFromSelectionClipboard();
virtual void ShowingContextMenu(bool showing);
virtual BackingStore* AllocBackingStore(const gfx::Size& size);
- virtual gfx::PluginWindowHandle CreatePluginContainer(
- base::ProcessId plugin_process_id);
- virtual void DestroyPluginContainer(gfx::PluginWindowHandle container);
- virtual void PluginProcessCrashed(base::ProcessId pid);
+ virtual void CreatePluginContainer(gfx::PluginWindowHandle id);
+ virtual void DestroyPluginContainer(gfx::PluginWindowHandle id);
gfx::NativeView native_view() const { return view_.get(); }
@@ -129,11 +127,6 @@ class RenderWidgetHostViewGtk : public RenderWidgetHostView {
// Helper class that lets us allocate plugin containers and move them.
GtkPluginContainerManager plugin_container_manager_;
-
- // A map of plugin process id -> windows related to that process.
- // Lets us clean up immediately when a plugin process crashes.
- typedef std::multimap<base::ProcessId, gfx::PluginWindowHandle> PluginPidMap;
- PluginPidMap plugin_pid_map_;
};
#endif // CHROME_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_VIEW_GTK_H_
diff --git a/chrome/browser/renderer_host/test/test_render_view_host.h b/chrome/browser/renderer_host/test/test_render_view_host.h
index 6ea898b..537c149 100644
--- a/chrome/browser/renderer_host/test/test_render_view_host.h
+++ b/chrome/browser/renderer_host/test/test_render_view_host.h
@@ -83,10 +83,8 @@ class TestRenderWidgetHostView : public RenderWidgetHostView {
#endif
#if defined(OS_LINUX)
- virtual gfx::PluginWindowHandle CreatePluginContainer(base::ProcessId) {
- return 0;
- }
- virtual void DestroyPluginContainer(gfx::PluginWindowHandle container) { }
+ virtual void CreatePluginContainer(gfx::PluginWindowHandle id) { }
+ virtual void DestroyPluginContainer(gfx::PluginWindowHandle id) { }
#endif
bool is_showing() const { return is_showing_; }
diff --git a/chrome/common/plugin_messages_internal.h b/chrome/common/plugin_messages_internal.h
index d2e2e64..4c1b985 100644
--- a/chrome/common/plugin_messages_internal.h
+++ b/chrome/common/plugin_messages_internal.h
@@ -238,15 +238,6 @@ IPC_BEGIN_MESSAGES(PluginHost)
IPC_SYNC_MESSAGE_ROUTED1_0(PluginHostMsg_SetWindow,
gfx::PluginWindowHandle /* window */)
-#if defined(OS_LINUX)
- // Asks the renderer to create a plugin container (GtkSocket).
- IPC_SYNC_MESSAGE_ROUTED0_1(PluginHostMsg_CreatePluginContainer,
- gfx::PluginWindowHandle /* container */)
- // Asks the renderer to destroy a plugin container (GtkSocket).
- IPC_SYNC_MESSAGE_ROUTED1_0(PluginHostMsg_DestroyPluginContainer,
- gfx::PluginWindowHandle /* container */)
-#endif
-
#if defined(OS_WIN)
// The modal_loop_pump_messages_event parameter is an event handle which is
// passed in for windowless plugins and is used to indicate if messages
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index 45a409b..891dbb7 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -1023,16 +1023,16 @@ IPC_BEGIN_MESSAGES(ViewHost)
#if defined(OS_LINUX)
// A renderer sends this when it needs a browser-side widget for
- // hosting a windowed plugin. The PID is the PID of the *plugin*
- // process, which is used to associate the browser-side container with
- // the lifetime of the plugin process.
- IPC_SYNC_MESSAGE_ROUTED1_1(ViewHostMsg_CreatePluginContainer,
- base::ProcessId /* pid */,
- gfx::PluginWindowHandle /* container */)
+ // hosting a windowed plugin. id is the XID of the plugin window, for which
+ // the container is created.
+ IPC_SYNC_MESSAGE_ROUTED1_0(ViewHostMsg_CreatePluginContainer,
+ gfx::PluginWindowHandle /* id */)
// Destroy a plugin container previously created using CreatePluginContainer.
+ // id is the XID of the plugin window corresponding to the container that is
+ // to be destroyed.
IPC_SYNC_MESSAGE_ROUTED1_0(ViewHostMsg_DestroyPluginContainer,
- gfx::PluginWindowHandle /* container */)
+ gfx::PluginWindowHandle /* id */)
#endif
// Clipboard IPC messages
diff --git a/chrome/plugin/webplugin_proxy.cc b/chrome/plugin/webplugin_proxy.cc
index 7d2598a..9a77484 100644
--- a/chrome/plugin/webplugin_proxy.cc
+++ b/chrome/plugin/webplugin_proxy.cc
@@ -5,9 +5,6 @@
#include "chrome/plugin/webplugin_proxy.h"
#include "build/build_config.h"
-#if defined(OS_LINUX)
-#include <gtk/gtk.h>
-#endif
#include "app/gfx/canvas.h"
#if defined(OS_WIN)
@@ -56,11 +53,6 @@ WebPluginProxy::WebPluginProxy(
delegate_(delegate),
waiting_for_paint_(false),
page_url_(page_url),
-#if defined(OS_LINUX)
- container_(0),
- plug_(NULL),
- socket_(NULL),
-#endif
ALLOW_THIS_IN_INITIALIZER_LIST(runnable_method_factory_(this))
{
}
@@ -74,42 +66,7 @@ bool WebPluginProxy::Send(IPC::Message* msg) {
return channel_->Send(msg);
}
-#if defined(OS_LINUX)
-gfx::PluginWindowHandle WebPluginProxy::CreatePluginContainer() {
- DCHECK(!container_);
- DCHECK(!plug_);
- DCHECK(!socket_);
-
- Send(new PluginHostMsg_CreatePluginContainer(route_id_, &container_));
- if (!container_)
- return 0;
-
- plug_ = gtk_plug_new(container_);
- gtk_widget_show(plug_);
- socket_ = gtk_socket_new();
- gtk_widget_show(socket_);
- gtk_container_add(GTK_CONTAINER(plug_), socket_);
- gtk_widget_show_all(plug_);
-
- // Prevent the plug from being destroyed if the browser kills the container
- // window.
- g_signal_connect(plug_, "delete-event", G_CALLBACK(gtk_true), NULL);
- // Prevent the socket from being destroyed when the plugin removes itself.
- g_signal_connect(socket_, "plug_removed", G_CALLBACK(gtk_true), NULL);
-
- return gtk_socket_get_id(GTK_SOCKET(socket_));
-}
-#endif
-
void WebPluginProxy::SetWindow(gfx::PluginWindowHandle window) {
-#if defined(OS_LINUX)
- if (window) {
- DCHECK(plug_);
- DCHECK(socket_);
- DCHECK_EQ(window, gtk_socket_get_id(GTK_SOCKET(socket_)));
- window = container_;
- }
-#endif
Send(new PluginHostMsg_SetWindow(route_id_, window));
}
@@ -119,14 +76,7 @@ void WebPluginProxy::WillDestroyWindow(gfx::PluginWindowHandle window) {
new PluginProcessHostMsg_PluginWindowDestroyed(
window, ::GetParent(window)));
#elif defined(OS_LINUX)
- DCHECK(plug_);
- DCHECK(socket_);
- DCHECK_EQ(window, gtk_socket_get_id(GTK_SOCKET(socket_)));
- Send(new PluginHostMsg_DestroyPluginContainer(route_id_, container_));
- gtk_widget_destroy(plug_);
- container_ = NULL;
- plug_ = NULL;
- socket_ = NULL;
+ // Nothing to do.
#else
NOTIMPLEMENTED();
#endif
diff --git a/chrome/plugin/webplugin_proxy.h b/chrome/plugin/webplugin_proxy.h
index 2b11e55..8e13638 100644
--- a/chrome/plugin/webplugin_proxy.h
+++ b/chrome/plugin/webplugin_proxy.h
@@ -42,9 +42,6 @@ class WebPluginProxy : public WebPlugin {
~WebPluginProxy();
// WebPlugin overrides
-#if defined(OS_LINUX)
- gfx::PluginWindowHandle CreatePluginContainer();
-#endif
void SetWindow(gfx::PluginWindowHandle window);
void WillDestroyWindow(gfx::PluginWindowHandle window);
#if defined(OS_WIN)
@@ -192,14 +189,6 @@ class WebPluginProxy : public WebPlugin {
scoped_ptr<TransportDIB> background_dib_;
scoped_ptr<skia::PlatformCanvas> windowless_canvas_;
scoped_ptr<skia::PlatformCanvas> background_canvas_;
-
- // On Linux some plugins assume that the GtkSocket container is in the same
- // process. So we create a GtkPlug to plug into the browser's container, and
- // a GtkSocket to hold the plugin. container_ is the original container XID
- // coming from the browser.
- gfx::PluginWindowHandle container_;
- GtkWidget *plug_;
- GtkWidget *socket_;
#endif
ScopedRunnableMethodFactory<WebPluginProxy> runnable_method_factory_;
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index 442b929..48caa47 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -3305,7 +3305,18 @@ void RenderView::DidMovePlugin(const WebPluginGeometry& move) {
SchedulePluginMove(move);
}
+void RenderView::CreatedPluginWindow(gfx::PluginWindowHandle window) {
+#if defined(OS_LINUX)
+ RenderThread::current()->Send(new ViewHostMsg_CreatePluginContainer(
+ routing_id(), window));
+#endif
+}
+
void RenderView::WillDestroyPluginWindow(gfx::PluginWindowHandle window) {
+#if defined(OS_LINUX)
+ RenderThread::current()->Send(new ViewHostMsg_DestroyPluginContainer(
+ routing_id(), window));
+#endif
CleanupWindowInPluginMoves(window);
}
diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h
index 48923c4..7317385 100644
--- a/chrome/renderer/render_view.h
+++ b/chrome/renderer/render_view.h
@@ -328,6 +328,7 @@ class RenderView : public RenderWidget,
virtual bool WasOpenedByUserGesture() const;
virtual void FocusAccessibilityObject(WebCore::AccessibilityObject* acc_obj);
virtual void DidMovePlugin(const WebPluginGeometry& move);
+ virtual void CreatedPluginWindow(gfx::PluginWindowHandle handle);
virtual void WillDestroyPluginWindow(gfx::PluginWindowHandle handle);
virtual void SpellCheck(const std::wstring& word, int* misspell_location,
int* misspell_length);
diff --git a/chrome/renderer/webplugin_delegate_proxy.cc b/chrome/renderer/webplugin_delegate_proxy.cc
index db73717..dc6a104 100644
--- a/chrome/renderer/webplugin_delegate_proxy.cc
+++ b/chrome/renderer/webplugin_delegate_proxy.cc
@@ -187,6 +187,9 @@ WebPluginDelegateProxy::~WebPluginDelegateProxy() {
}
void WebPluginDelegateProxy::PluginDestroyed() {
+ if (window_) {
+ WillDestroyWindow();
+ }
plugin_ = NULL;
if (npobject_) {
@@ -358,12 +361,6 @@ void WebPluginDelegateProxy::OnMessageReceived(const IPC::Message& msg) {
IPC_BEGIN_MESSAGE_MAP(WebPluginDelegateProxy, msg)
IPC_MESSAGE_HANDLER(PluginHostMsg_SetWindow, OnSetWindow)
-#if defined(OS_LINUX)
- IPC_MESSAGE_HANDLER(PluginHostMsg_CreatePluginContainer,
- OnCreatePluginContainer)
- IPC_MESSAGE_HANDLER(PluginHostMsg_DestroyPluginContainer,
- OnDestroyPluginContainer)
-#endif
#if defined(OS_WIN)
IPC_MESSAGE_HANDLER(PluginHostMsg_SetWindowlessPumpEvent,
OnSetWindowlessPumpEvent)
@@ -399,7 +396,7 @@ void WebPluginDelegateProxy::OnChannelError() {
if (window_) {
// The actual WebPluginDelegate never got a chance to tell the WebPlugin
// its window was going away. Do it on its behalf.
- plugin_->WillDestroyWindow(window_);
+ WillDestroyWindow();
}
plugin_->Invalidate();
}
@@ -757,22 +754,14 @@ void WebPluginDelegateProxy::OnSetWindow(gfx::PluginWindowHandle window) {
plugin_->SetWindow(window);
}
-#if defined(OS_LINUX)
-void WebPluginDelegateProxy::OnCreatePluginContainer(
- gfx::PluginWindowHandle* container) {
- RenderThread::current()->Send(new ViewHostMsg_CreatePluginContainer(
- render_view_->routing_id(), GetProcessId(), container));
+void WebPluginDelegateProxy::WillDestroyWindow() {
+ DCHECK(window_);
+ plugin_->WillDestroyWindow(window_);
+ window_ = NULL;
}
-void WebPluginDelegateProxy::OnDestroyPluginContainer(
- gfx::PluginWindowHandle container) {
- RenderThread::current()->Send(new ViewHostMsg_DestroyPluginContainer(
- render_view_->routing_id(), container));
-}
-#endif
-
#if defined(OS_WIN)
- void WebPluginDelegateProxy::OnSetWindowlessPumpEvent(
+void WebPluginDelegateProxy::OnSetWindowlessPumpEvent(
HANDLE modal_loop_pump_messages_event) {
DCHECK(modal_loop_pump_messages_event_ == NULL);
diff --git a/chrome/renderer/webplugin_delegate_proxy.h b/chrome/renderer/webplugin_delegate_proxy.h
index 808c06e..5680d9e 100644
--- a/chrome/renderer/webplugin_delegate_proxy.h
+++ b/chrome/renderer/webplugin_delegate_proxy.h
@@ -108,10 +108,6 @@ class WebPluginDelegateProxy : public WebPluginDelegate,
// Message handlers for messages that proxy WebPlugin methods, which
// we translate into calls to the real WebPlugin.
void OnSetWindow(gfx::PluginWindowHandle window);
-#if defined(OS_LINUX)
- void OnCreatePluginContainer(gfx::PluginWindowHandle* container);
- void OnDestroyPluginContainer(gfx::PluginWindowHandle container);
-#endif
#if defined(OS_WIN)
void OnSetWindowlessPumpEvent(HANDLE modal_loop_pump_messages_event);
#endif
@@ -163,6 +159,11 @@ class WebPluginDelegateProxy : public WebPluginDelegate,
bool CreateBitmap(scoped_ptr<TransportDIB>* memory,
scoped_ptr<skia::PlatformCanvas>* canvas);
+ // Called for cleanup during plugin destruction. Normally right before the
+ // plugin window gets destroyed, or when the plugin has crashed (at which
+ // point the window has already been destroyed).
+ void WillDestroyWindow();
+
RenderView* render_view_;
WebPlugin* plugin_;
bool windowless_;
diff --git a/webkit/glue/plugins/gtk_plugin_container.cc b/webkit/glue/plugins/gtk_plugin_container.cc
index c487fa0..c80bbf1 100644
--- a/webkit/glue/plugins/gtk_plugin_container.cc
+++ b/webkit/glue/plugins/gtk_plugin_container.cc
@@ -35,7 +35,7 @@ class GtkPluginContainer : public GtkSocket {
NULL, NULL,
static_cast<GClassInitFunc>(&ClassInit),
NULL, NULL,
- sizeof(GtkSocket), // We are identical to a GtkSocket.
+ sizeof(GtkPluginContainer),
0, &InstanceInit,
};
type = g_type_register_static(GTK_TYPE_SOCKET,
diff --git a/webkit/glue/plugins/gtk_plugin_container_manager.cc b/webkit/glue/plugins/gtk_plugin_container_manager.cc
index 266687b..4683e08 100644
--- a/webkit/glue/plugins/gtk_plugin_container_manager.cc
+++ b/webkit/glue/plugins/gtk_plugin_container_manager.cc
@@ -11,54 +11,44 @@
#include "webkit/glue/plugins/gtk_plugin_container.h"
#include "webkit/glue/webplugin.h"
-// Helper function that always returns true. Used to prevent Gtk from
-// destroying our socket when the plug goes away: we manage it ourselves.
-static gboolean AlwaysTrue(void* unused) {
- return TRUE;
-}
-
-gfx::PluginWindowHandle GtkPluginContainerManager::CreatePluginContainer() {
+GtkWidget* GtkPluginContainerManager::CreatePluginContainer(
+ gfx::PluginWindowHandle id) {
DCHECK(host_widget_);
- // If the current view hasn't been attached to a top-level window (e.g. it is
- // loaded in a background tab), it can't be realized without asserting in
- // Gtk, so we can't get the XID for the socket. Instead, don't create one.
- // We'll never see the plugin but it's better than crashing.
- // TODO(piman@google.com): figure out how to add the background tab to the
- // widget hierarchy, so that it can be realized. It doesn't have to be
- // visible.
- if (!gtk_widget_get_ancestor(host_widget_, GTK_TYPE_WINDOW)) {
- NOTIMPLEMENTED() << "Can't create plugins in background tabs.";
- return 0;
- }
-
- GtkWidget* plugin_container = gtk_plugin_container_new();
- g_signal_connect(G_OBJECT(plugin_container), "plug-removed",
- G_CALLBACK(AlwaysTrue), NULL);
- // Add a connection to the "unrealize" signal so that if the parent widget
- // gets destroyed before the DestroyPluginContainer gets called, bad things
- // don't happen.
- g_signal_connect(G_OBJECT(plugin_container), "unrealize",
- G_CALLBACK(UnrealizeCallback), this);
- gtk_container_add(GTK_CONTAINER(host_widget_), plugin_container);
- gtk_widget_show(plugin_container);
- gtk_widget_realize(plugin_container);
-
- gfx::PluginWindowHandle id = gtk_socket_get_id(GTK_SOCKET(plugin_container));
-
- plugin_window_to_widget_map_.insert(std::make_pair(id, plugin_container));
-
- return id;
+ GtkWidget *widget = gtk_plugin_container_new();
+ plugin_window_to_widget_map_.insert(std::make_pair(id, widget));
+
+ // The Realize callback is responsible for adding the plug into the socket.
+ // The reason is 2-fold:
+ // - the plug can't be added until the socket is realized, but this may not
+ // happen until the socket is attached to a top-level window, which isn't the
+ // case for background tabs.
+ // - when dragging tabs, the socket gets unrealized, which breaks the XEMBED
+ // connection. We need to make it again when the tab is reattached, and the
+ // socket gets realized again.
+ //
+ // Note, the RealizeCallback relies on the plugin_window_to_widget_map_ to
+ // have the mapping.
+ g_signal_connect(G_OBJECT(widget), "realize",
+ G_CALLBACK(RealizeCallback), this);
+
+ // Don't destroy the widget when the plug is removed.
+ g_signal_connect(G_OBJECT(widget), "plug-removed",
+ G_CALLBACK(gtk_true), NULL);
+
+ gtk_container_add(GTK_CONTAINER(host_widget_), widget);
+ gtk_widget_show(widget);
+
+ return widget;
}
void GtkPluginContainerManager::DestroyPluginContainer(
- gfx::PluginWindowHandle container) {
- GtkWidget* plugin_container = MapIDToWidget(container);
- if (!plugin_container)
- return;
+ gfx::PluginWindowHandle id) {
+ DCHECK(host_widget_);
+ GtkWidget* widget = MapIDToWidget(id);
+ if (widget)
+ gtk_widget_destroy(widget);
- // This will call the UnrealizeCallback that will remove plugin_container
- // from the map.
- gtk_widget_destroy(plugin_container);
+ plugin_window_to_widget_map_.erase(id);
}
void GtkPluginContainerManager::MovePluginContainer(
@@ -117,7 +107,8 @@ void GtkPluginContainerManager::MovePluginContainer(
move.window_rect.height());
}
-GtkWidget* GtkPluginContainerManager::MapIDToWidget(gfx::PluginWindowHandle id) {
+GtkWidget* GtkPluginContainerManager::MapIDToWidget(
+ gfx::PluginWindowHandle id) {
PluginWindowToWidgetMap::const_iterator i =
plugin_window_to_widget_map_.find(id);
if (i != plugin_window_to_widget_map_.end())
@@ -128,12 +119,26 @@ GtkWidget* GtkPluginContainerManager::MapIDToWidget(gfx::PluginWindowHandle id)
return NULL;
}
-void GtkPluginContainerManager::UnrealizeCallback(GtkWidget* widget,
- void* user_data) {
- // This is the last chance to get the XID for the widget. Remove it from the
- // map here.
+gfx::PluginWindowHandle GtkPluginContainerManager::MapWidgetToID(
+ GtkWidget* widget) {
+ for (PluginWindowToWidgetMap::const_iterator i =
+ plugin_window_to_widget_map_.begin();
+ i != plugin_window_to_widget_map_.end(); ++i) {
+ if (i->second == widget)
+ return i->first;
+ }
+
+ LOG(ERROR) << "Request for id for unknown widget";
+ return 0;
+}
+
+// static
+void GtkPluginContainerManager::RealizeCallback(GtkWidget* widget,
+ void* user_data) {
GtkPluginContainerManager* plugin_container_manager =
static_cast<GtkPluginContainerManager*>(user_data);
- gfx::PluginWindowHandle id = gtk_socket_get_id(GTK_SOCKET(widget));
- plugin_container_manager->plugin_window_to_widget_map_.erase(id);
+
+ gfx::PluginWindowHandle id = plugin_container_manager->MapWidgetToID(widget);
+ if (id)
+ gtk_socket_add_id(GTK_SOCKET(widget), id);
}
diff --git a/webkit/glue/plugins/gtk_plugin_container_manager.h b/webkit/glue/plugins/gtk_plugin_container_manager.h
index 648e963..30a6b1a 100644
--- a/webkit/glue/plugins/gtk_plugin_container_manager.h
+++ b/webkit/glue/plugins/gtk_plugin_container_manager.h
@@ -21,28 +21,31 @@ class GtkPluginContainerManager {
// Sets the widget that will host the plugin containers. Must be a GtkFixed.
void set_host_widget(GtkWidget *widget) { host_widget_ = widget; }
- // Creates a new plugin container, returning its XID.
- gfx::PluginWindowHandle CreatePluginContainer();
+ // Creates a new plugin container, for a given plugin XID.
+ GtkWidget* CreatePluginContainer(gfx::PluginWindowHandle id);
- // Destroys a plugin container, given its XID.
- void DestroyPluginContainer(gfx::PluginWindowHandle container);
+ // Destroys a plugin container, given the plugin XID.
+ void DestroyPluginContainer(gfx::PluginWindowHandle id);
// Takes an update from WebKit about a plugin's position and side and moves
// the plugin accordingly.
void MovePluginContainer(const WebPluginGeometry& move);
private:
- // Maps a plugin container XID to the corresponding widget.
+ // Maps a plugin XID to the corresponding container widget.
GtkWidget* MapIDToWidget(gfx::PluginWindowHandle id);
- // Callback for when the plugin container loses its XID, so that it can be
- // removed from plugin_window_to_widget_map_.
- static void UnrealizeCallback(GtkWidget *widget, void *user_data);
+ // Maps a container widget to the corresponding plugin XID.
+ gfx::PluginWindowHandle MapWidgetToID(GtkWidget* widget);
+
+ // Callback for when the plugin container gets realized, at which point it
+ // plugs the plugin XID.
+ static void RealizeCallback(GtkWidget *widget, void *user_data);
// Parent of the plugin containers.
GtkWidget* host_widget_;
- // A map that associates plugin containers to their XID.
+ // A map that associates plugin containers to the plugin XID.
typedef std::map<gfx::PluginWindowHandle, GtkWidget*> PluginWindowToWidgetMap;
PluginWindowToWidgetMap plugin_window_to_widget_map_;
};
diff --git a/webkit/glue/plugins/webplugin_delegate_impl.h b/webkit/glue/plugins/webplugin_delegate_impl.h
index 106a040..90d8203 100644
--- a/webkit/glue/plugins/webplugin_delegate_impl.h
+++ b/webkit/glue/plugins/webplugin_delegate_impl.h
@@ -196,6 +196,13 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
GdkPixmap* pixmap_;
double first_event_time_;
+ // On Linux some plugins assume that the GtkSocket container is in the same
+ // process. So we create a GtkPlug to plug into the browser's container, and
+ // a GtkSocket to hold the plugin. We then send the GtkPlug to the browser
+ // process.
+ GtkWidget* plug_;
+ GtkWidget* socket_;
+
// Ensure pixmap_ exists and is at least width by height pixels.
void EnsurePixmapAtLeastSize(int width, int height);
#endif
diff --git a/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc b/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc
index da236b4..83d348b 100644
--- a/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc
+++ b/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc
@@ -68,6 +68,8 @@ WebPluginDelegateImpl::WebPluginDelegateImpl(
instance_(instance),
pixmap_(NULL),
first_event_time_(-1.0),
+ plug_(NULL),
+ socket_(NULL),
parent_(containing_view),
quirks_(0) {
memset(&window_, 0, sizeof(window_));
@@ -134,8 +136,10 @@ bool WebPluginDelegateImpl::Initialize(const GURL& url,
if (!WindowedCreatePlugin())
return false;
}
+ gfx::PluginWindowHandle handle =
+ windowless_ ? 0 : gtk_plug_get_id(GTK_PLUG(plug_));
+ plugin->SetWindow(handle);
- plugin->SetWindow(windowed_handle_);
plugin_url_ = url.spec();
return true;
@@ -258,6 +262,7 @@ void WebPluginDelegateImpl::WindowedUpdateGeometry(
bool WebPluginDelegateImpl::WindowedCreatePlugin() {
DCHECK(!windowed_handle_);
+ DCHECK(!plug_);
bool xembed;
NPError err = instance_->NPP_GetValue(NPPVpluginNeedsXEmbed, &xembed);
@@ -267,11 +272,22 @@ bool WebPluginDelegateImpl::WindowedCreatePlugin() {
return false;
}
- // Xembed plugins need a window created for them browser-side.
- // Do that now.
- windowed_handle_ = plugin_->CreatePluginContainer();
- if (!windowed_handle_)
- return false;
+ // Passing 0 as the socket XID creates a plug without plugging it in a socket
+ // yet, so that it can be latter added with gtk_socket_add_id().
+ plug_ = gtk_plug_new(0);
+ gtk_widget_show(plug_);
+ socket_ = gtk_socket_new();
+ gtk_widget_show(socket_);
+ gtk_container_add(GTK_CONTAINER(plug_), socket_);
+ gtk_widget_show_all(plug_);
+
+ // Prevent the plug from being destroyed if the browser kills the container
+ // window.
+ g_signal_connect(plug_, "delete-event", G_CALLBACK(gtk_true), NULL);
+ // Prevent the socket from being destroyed when the plugin removes itself.
+ g_signal_connect(socket_, "plug_removed", G_CALLBACK(gtk_true), NULL);
+
+ windowed_handle_ = gtk_socket_get_id(GTK_SOCKET(socket_));
window_.window = reinterpret_cast<void*>(windowed_handle_);
@@ -288,9 +304,12 @@ bool WebPluginDelegateImpl::WindowedCreatePlugin() {
}
void WebPluginDelegateImpl::WindowedDestroyWindow() {
- if (windowed_handle_) {
- plugin_->WillDestroyWindow(windowed_handle_);
+ if (plug_) {
+ plugin_->WillDestroyWindow(gtk_plug_get_id(GTK_PLUG(plug_)));
+ gtk_widget_destroy(plug_);
+ plug_ = NULL;
+ socket_ = NULL;
windowed_handle_ = 0;
}
}
diff --git a/webkit/glue/webplugin.h b/webkit/glue/webplugin.h
index d5f0cf6..886b031 100644
--- a/webkit/glue/webplugin.h
+++ b/webkit/glue/webplugin.h
@@ -25,7 +25,8 @@ struct NPObject;
// Describes the new location for a plugin window.
struct WebPluginGeometry {
// On Windows, this is the plugin window in the plugin process.
- // On X11, this is the browser process's hosting window (the GtkSocket).
+ // On X11, this is the XID of the plugin-side GtkPlug containing the
+ // GtkSocket hosting the actual plugin window.
gfx::PluginWindowHandle window;
gfx::Rect window_rect;
// Clip rect (include) and cutouts (excludes), relative to
@@ -51,13 +52,6 @@ class WebPlugin {
WebPlugin() { }
virtual ~WebPlugin() { }
-#if defined(OS_LINUX)
- // Called by the plugin delegate to request a container for a new
- // windowed plugin. This handle will later get destroyed with
- // WillDestroyWindow.
- virtual gfx::PluginWindowHandle CreatePluginContainer() = 0;
-#endif
-
// Called by the plugin delegate to let the WebPlugin know if the plugin is
// windowed (i.e. handle is not NULL) or windowless (handle is NULL). This
// tells the WebPlugin to send mouse/keyboard events to the plugin delegate,
diff --git a/webkit/glue/webplugin_impl.cc b/webkit/glue/webplugin_impl.cc
index 3fe6b58..397fbd2 100644
--- a/webkit/glue/webplugin_impl.cc
+++ b/webkit/glue/webplugin_impl.cc
@@ -396,19 +396,17 @@ void WebPluginImpl::didFailLoading(const WebURLError& error) {
WebPluginImpl::~WebPluginImpl() {
}
-#if defined(OS_LINUX)
-gfx::PluginWindowHandle WebPluginImpl::CreatePluginContainer() {
- WebViewDelegate* view_delegate = GetWebViewDelegate();
- if (!view_delegate)
- return 0;
- return view_delegate->CreatePluginContainer();
-}
-#endif
void WebPluginImpl::SetWindow(gfx::PluginWindowHandle window) {
if (window) {
DCHECK(!windowless_); // Make sure not called twice.
window_ = window;
+ WebViewDelegate* view_delegate = GetWebViewDelegate();
+ if (view_delegate) {
+ // Tell the view delegate that the plugin window was created, so that it
+ // can create necessary container widgets.
+ view_delegate->CreatedPluginWindow(window);
+ }
} else {
DCHECK(!window_); // Make sure not called twice.
windowless_ = true;
diff --git a/webkit/glue/webplugin_impl.h b/webkit/glue/webplugin_impl.h
index fd83ba9..7f98759 100644
--- a/webkit/glue/webplugin_impl.h
+++ b/webkit/glue/webplugin_impl.h
@@ -100,9 +100,6 @@ class WebPluginImpl : public WebPlugin,
virtual void didFailLoading(const WebKit::WebURLError& error);
// WebPlugin implementation:
-#if defined(OS_LINUX)
- gfx::PluginWindowHandle CreatePluginContainer();
-#endif
void SetWindow(gfx::PluginWindowHandle window);
void WillDestroyWindow(gfx::PluginWindowHandle window);
#if defined(OS_WIN)
diff --git a/webkit/glue/webview_delegate.h b/webkit/glue/webview_delegate.h
index 826d1a7..6bf918c 100644
--- a/webkit/glue/webview_delegate.h
+++ b/webkit/glue/webview_delegate.h
@@ -149,9 +149,9 @@ class WebViewDelegate : virtual public WebKit::WebWidgetClient {
return NULL;
}
- // Called when a windowed plugin is initializing, to request a container
- // for the plugin. Only used on Linux.
- virtual gfx::PluginWindowHandle CreatePluginContainer() { return 0; }
+ // Called when a windowed plugin is created.
+ // Lets the view delegate create anything it is using to wrap the plugin.
+ virtual void CreatedPluginWindow(gfx::PluginWindowHandle handle) { }
// Called when a windowed plugin is closing.
// Lets the view delegate shut down anything it is using to wrap the plugin.
diff --git a/webkit/tools/test_shell/test_webview_delegate.h b/webkit/tools/test_shell/test_webview_delegate.h
index 6224b9c..971f199 100644
--- a/webkit/tools/test_shell/test_webview_delegate.h
+++ b/webkit/tools/test_shell/test_webview_delegate.h
@@ -77,8 +77,8 @@ class TestWebViewDelegate : public WebViewDelegate {
const std::string& clsid,
std::string* actual_mime_type);
#if defined(OS_LINUX)
- virtual gfx::PluginWindowHandle CreatePluginContainer();
- virtual void WillDestroyPluginWindow(gfx::PluginWindowHandle handle);
+ virtual void CreatedPluginWindow(gfx::PluginWindowHandle id);
+ virtual void WillDestroyPluginWindow(gfx::PluginWindowHandle id);
#endif
virtual WebKit::WebMediaPlayer* CreateWebMediaPlayer(
WebKit::WebMediaPlayerClient* client);
diff --git a/webkit/tools/test_shell/test_webview_delegate_gtk.cc b/webkit/tools/test_shell/test_webview_delegate_gtk.cc
index 460dceb..461d1d3 100644
--- a/webkit/tools/test_shell/test_webview_delegate_gtk.cc
+++ b/webkit/tools/test_shell/test_webview_delegate_gtk.cc
@@ -108,12 +108,12 @@ WebPluginDelegate* TestWebViewDelegate::CreatePluginDelegate(
return WebPluginDelegateImpl::Create(info.path, mtype, plugin_parent);
}
-gfx::PluginWindowHandle TestWebViewDelegate::CreatePluginContainer() {
- return shell_->webViewHost()->CreatePluginContainer();
+void TestWebViewDelegate::CreatedPluginWindow(gfx::PluginWindowHandle id) {
+ shell_->webViewHost()->CreatePluginContainer(id);
}
-void TestWebViewDelegate::WillDestroyPluginWindow(unsigned long id) {
- shell_->webViewHost()->OnPluginWindowDestroyed(id);
+void TestWebViewDelegate::WillDestroyPluginWindow(gfx::PluginWindowHandle id) {
+ shell_->webViewHost()->DestroyPluginContainer(id);
}
void TestWebViewDelegate::ShowJavaScriptAlert(const std::wstring& message) {
diff --git a/webkit/tools/test_shell/webview_host.h b/webkit/tools/test_shell/webview_host.h
index 962633b..3c95e1d 100644
--- a/webkit/tools/test_shell/webview_host.h
+++ b/webkit/tools/test_shell/webview_host.h
@@ -32,12 +32,11 @@ class WebViewHost : public WebWidgetHost {
WebView* webview() const;
#if defined(OS_LINUX)
- // Create a new plugin parent container, returning its X window id for
- // embedders to use.
- GdkNativeWindow CreatePluginContainer();
+ // Create a new plugin parent container for a given plugin XID.
+ void CreatePluginContainer(gfx::PluginWindowHandle id);
- // Called when a plugin has been destroyed. Lets us clean up our side.
- void OnPluginWindowDestroyed(GdkNativeWindow id);
+ // Destroy the plugin parent container when a plugin has been destroyed.
+ void DestroyPluginContainer(gfx::PluginWindowHandle id);
GtkPluginContainerManager* plugin_container_manager() {
return &plugin_container_manager_;
diff --git a/webkit/tools/test_shell/webview_host_gtk.cc b/webkit/tools/test_shell/webview_host_gtk.cc
index 39a88ab..6554cc5 100644
--- a/webkit/tools/test_shell/webview_host_gtk.cc
+++ b/webkit/tools/test_shell/webview_host_gtk.cc
@@ -35,10 +35,10 @@ WebView* WebViewHost::webview() const {
return static_cast<WebView*>(webwidget_);
}
-GdkNativeWindow WebViewHost::CreatePluginContainer() {
- return plugin_container_manager_.CreatePluginContainer();
+void WebViewHost::CreatePluginContainer(gfx::PluginWindowHandle id) {
+ plugin_container_manager_.CreatePluginContainer(id);
}
-void WebViewHost::OnPluginWindowDestroyed(GdkNativeWindow id) {
+void WebViewHost::DestroyPluginContainer(gfx::PluginWindowHandle id) {
plugin_container_manager_.DestroyPluginContainer(id);
}