Commit c4eac73e authored by agl@chromium.org's avatar agl@chromium.org

Linux: terminate clipboard handling on the UI thread.

After discussing with various people, I think we're going to do this
in the short term at least. Currently we're calling into GTK from the
IO thread and Bad Things Happen when one does that.

We would like to write an Xlib, fully asynchronous system for dealing
with the clipboard (and to get the clipboard stuff out of base!). That
would let us avoid sending the selection over the IPC channel each
time it updates too.

However, that's going to be a lot of work and we have crashing
browsers happening /right now/. Also, Evan thinks that maybe we don't
have the deadlock situation on Linux that we do on Windows with
terminating sync requests from the renderer on the UI thread.

http://codereview.chromium.org/100238

BUG=9865


git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15028 0039d316-1c4b-4281-b951-d872f2087c98
parent 29a596b6
......@@ -264,13 +264,16 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& message) {
OnClipboardWriteObjects)
IPC_MESSAGE_HANDLER(ViewHostMsg_ClipboardWriteObjectsSync,
OnClipboardWriteObjects)
IPC_MESSAGE_HANDLER(ViewHostMsg_ClipboardIsFormatAvailable,
OnClipboardIsFormatAvailable)
IPC_MESSAGE_HANDLER(ViewHostMsg_ClipboardReadText, OnClipboardReadText)
IPC_MESSAGE_HANDLER(ViewHostMsg_ClipboardReadAsciiText,
OnClipboardReadAsciiText)
IPC_MESSAGE_HANDLER(ViewHostMsg_ClipboardReadHTML,
OnClipboardReadHTML)
IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ClipboardIsFormatAvailable,
OnClipboardIsFormatAvailable)
IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ClipboardReadText,
OnClipboardReadText)
IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ClipboardReadAsciiText,
OnClipboardReadAsciiText)
IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ClipboardReadHTML,
OnClipboardReadHTML)
IPC_MESSAGE_HANDLER(ViewHostMsg_GetMimeTypeFromExtension,
OnGetMimeTypeFromExtension)
IPC_MESSAGE_HANDLER(ViewHostMsg_GetMimeTypeFromFile,
......@@ -555,27 +558,51 @@ void ResourceMessageFilter::OnClipboardWriteObjects(
new WriteClipboardTask(long_living_objects));
}
#if !defined(OS_LINUX)
// On non-Linux platforms, clipboard actions can be performed on the IO thread.
// On Linux, since the clipboard is linked with GTK, we either have to do this
// with GTK on the UI thread, or with Xlib on the BACKGROUND_X11 thread. In an
// ideal world, we would do the latter. However, for now we're going to
// terminate these calls on the UI thread. This risks deadlock in the case of
// plugins, but it's better than crashing which is what doing on the IO thread
// gives us.
//
// See resource_message_filter_gtk.cc for the Linux implementation of these
// functions.
void ResourceMessageFilter::OnClipboardIsFormatAvailable(
Clipboard::FormatType format, bool* result) {
DCHECK(result);
*result = GetClipboardService()->IsFormatAvailable(format);
Clipboard::FormatType format, IPC::Message* reply) {
const bool result = GetClipboardService()->IsFormatAvailable(format);
ViewHostMsg_ClipboardIsFormatAvailable::WriteReplyParams(reply, result);
Send(reply);
}
void ResourceMessageFilter::OnClipboardReadText(string16* result) {
GetClipboardService()->ReadText(result);
void ResourceMessageFilter::OnClipboardReadText(IPC::Message* reply) {
string16 result;
GetClipboardService()->ReadText(&result);
ViewHostMsg_ClipboardReadText::WriteReplyParams(reply, result);
Send(reply);
}
void ResourceMessageFilter::OnClipboardReadAsciiText(std::string* result) {
GetClipboardService()->ReadAsciiText(result);
void ResourceMessageFilter::OnClipboardReadAsciiText(IPC::Message* reply) {
std::string result;
GetClipboardService()->ReadAsciiText(&result);
ViewHostMsg_ClipboardReadAsciiText::WriteReplyParams(reply, result);
Send(reply);
}
void ResourceMessageFilter::OnClipboardReadHTML(string16* markup,
GURL* src_url) {
void ResourceMessageFilter::OnClipboardReadHTML(IPC::Message* reply) {
std::string src_url_str;
GetClipboardService()->ReadHTML(markup, &src_url_str);
*src_url = GURL(src_url_str);
string16 markup;
GetClipboardService()->ReadHTML(&markup, &src_url_str);
const GURL src_url = GURL(src_url_str);
ViewHostMsg_ClipboardReadHTML::WriteReplyParams(reply, markup, src_url);
Send(reply);
}
#endif
void ResourceMessageFilter::OnGetMimeTypeFromExtension(
const FilePath::StringType& ext, std::string* mime_type) {
net::GetMimeTypeFromExtension(ext, mime_type);
......
......@@ -151,10 +151,13 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter,
void OnReceiveContextMenuMsg(const IPC::Message& msg);
// Clipboard messages
void OnClipboardWriteObjects(const Clipboard::ObjectMap& objects);
void OnClipboardIsFormatAvailable(Clipboard::FormatType format, bool* result);
void OnClipboardReadText(string16* result);
void OnClipboardReadAsciiText(std::string* result);
void OnClipboardReadHTML(string16* markup, GURL* src_url);
void OnClipboardIsFormatAvailable(Clipboard::FormatType format,
IPC::Message* reply);
void OnClipboardReadText(IPC::Message* reply);
void OnClipboardReadAsciiText(IPC::Message* reply);
void OnClipboardReadHTML(IPC::Message* reply);
void OnGetWindowRect(gfx::NativeViewId window, IPC::Message* reply);
void OnGetRootWindowRect(gfx::NativeViewId window, IPC::Message* reply);
void OnGetMimeTypeFromExtension(const FilePath::StringType& ext,
......@@ -203,10 +206,15 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter,
void OnExtensionPostMessage(int port_id, const std::string& message);
#if defined(OS_LINUX)
void SendBackgroundX11Reply(IPC::Message* reply_msg);
void SendDelayedReply(IPC::Message* reply_msg);
void DoOnGetScreenInfo(gfx::NativeViewId view, IPC::Message* reply_msg);
void DoOnGetWindowRect(gfx::NativeViewId view, IPC::Message* reply_msg);
void DoOnGetRootWindowRect(gfx::NativeViewId view, IPC::Message* reply_msg);
void DoOnClipboardIsFormatAvailable(Clipboard::FormatType format,
IPC::Message* reply_msg);
void DoOnClipboardReadText(IPC::Message* reply_msg);
void DoOnClipboardReadAsciiText(IPC::Message* reply_msg);
void DoOnClipboardReadHTML(IPC::Message* reply_msg);
#endif
// We have our own clipboard service because we want to access the clipboard
......
......@@ -4,8 +4,10 @@
#include "chrome/browser/renderer_host/resource_message_filter.h"
#include "base/clipboard.h"
#include "base/gfx/gtk_native_view_id_manager.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/common/clipboard_service.h"
#include "chrome/common/render_messages.h"
#include "chrome/common/x11_util.h"
......@@ -19,7 +21,7 @@ using WebKit::WebScreenInfoFactory;
// http://crbug.com/9060 for more details.
// Called on the IO thread.
void ResourceMessageFilter::SendBackgroundX11Reply(IPC::Message* reply_msg) {
void ResourceMessageFilter::SendDelayedReply(IPC::Message* reply_msg) {
Send(reply_msg);
}
......@@ -33,7 +35,7 @@ void ResourceMessageFilter::DoOnGetScreenInfo(gfx::NativeViewId view,
ChromeThread::GetMessageLoop(ChromeThread::IO)->PostTask(
FROM_HERE, NewRunnableMethod(
this, &ResourceMessageFilter::SendBackgroundX11Reply, reply_msg));
this, &ResourceMessageFilter::SendDelayedReply, reply_msg));
}
// Called on the BACKGROUND_X11 thread.
......@@ -57,7 +59,7 @@ void ResourceMessageFilter::DoOnGetWindowRect(gfx::NativeViewId view,
ChromeThread::GetMessageLoop(ChromeThread::IO)->PostTask(
FROM_HERE, NewRunnableMethod(
this, &ResourceMessageFilter::SendBackgroundX11Reply, reply_msg));
this, &ResourceMessageFilter::SendDelayedReply, reply_msg));
}
// Return the top-level parent of the given window. Called on the
......@@ -96,7 +98,58 @@ void ResourceMessageFilter::DoOnGetRootWindowRect(gfx::NativeViewId view,
ChromeThread::GetMessageLoop(ChromeThread::IO)->PostTask(
FROM_HERE, NewRunnableMethod(
this, &ResourceMessageFilter::SendBackgroundX11Reply, reply_msg));
this, &ResourceMessageFilter::SendDelayedReply, reply_msg));
}
// Called on the UI thread.
void ResourceMessageFilter::DoOnClipboardIsFormatAvailable(
Clipboard::FormatType format, IPC::Message* reply_msg) {
const bool result = GetClipboardService()->IsFormatAvailable(format);
ViewHostMsg_ClipboardIsFormatAvailable::WriteReplyParams(reply_msg, result);
ChromeThread::GetMessageLoop(ChromeThread::IO)->PostTask(
FROM_HERE, NewRunnableMethod(
this, &ResourceMessageFilter::SendDelayedReply, reply_msg));
}
// Called on the UI thread.
void ResourceMessageFilter::DoOnClipboardReadText(IPC::Message* reply_msg) {
string16 result;
GetClipboardService()->ReadText(&result);
ViewHostMsg_ClipboardReadText::WriteReplyParams(reply_msg, result);
ChromeThread::GetMessageLoop(ChromeThread::IO)->PostTask(
FROM_HERE, NewRunnableMethod(
this, &ResourceMessageFilter::SendDelayedReply, reply_msg));
}
// Called on the UI thread.
void ResourceMessageFilter::DoOnClipboardReadAsciiText(
IPC::Message* reply_msg) {
std::string result;
GetClipboardService()->ReadAsciiText(&result);
ViewHostMsg_ClipboardReadAsciiText::WriteReplyParams(reply_msg, result);
ChromeThread::GetMessageLoop(ChromeThread::IO)->PostTask(
FROM_HERE, NewRunnableMethod(
this, &ResourceMessageFilter::SendDelayedReply, reply_msg));
}
// Called on the UI thread.
void ResourceMessageFilter::DoOnClipboardReadHTML(IPC::Message* reply_msg) {
std::string src_url_str;
string16 markup;
GetClipboardService()->ReadHTML(&markup, &src_url_str);
const GURL src_url = GURL(src_url_str);
ViewHostMsg_ClipboardReadHTML::WriteReplyParams(reply_msg, markup, src_url);
ChromeThread::GetMessageLoop(ChromeThread::IO)->PostTask(
FROM_HERE, NewRunnableMethod(
this, &ResourceMessageFilter::SendDelayedReply, reply_msg));
}
// Called on the IO thread.
......@@ -122,3 +175,29 @@ void ResourceMessageFilter::OnGetRootWindowRect(gfx::NativeViewId view,
FROM_HERE, NewRunnableMethod(
this, &ResourceMessageFilter::DoOnGetRootWindowRect, view, reply_msg));
}
// Called on the IO thread.
void ResourceMessageFilter::OnClipboardIsFormatAvailable(
Clipboard::FormatType format, IPC::Message* reply_msg) {
ui_loop()->PostTask(FROM_HERE, NewRunnableMethod(
this, &ResourceMessageFilter::DoOnClipboardIsFormatAvailable, format,
reply_msg));
}
// Called on the IO thread.
void ResourceMessageFilter::OnClipboardReadText(IPC::Message* reply_msg) {
ui_loop()->PostTask(FROM_HERE, NewRunnableMethod(
this, &ResourceMessageFilter::DoOnClipboardReadText, reply_msg));
}
// Called on the IO thread.
void ResourceMessageFilter::OnClipboardReadAsciiText(IPC::Message* reply_msg) {
ui_loop()->PostTask(FROM_HERE, NewRunnableMethod(
this, &ResourceMessageFilter::DoOnClipboardReadAsciiText, reply_msg));
}
// Called on the IO thread.
void ResourceMessageFilter::OnClipboardReadHTML(IPC::Message* reply_msg) {
ui_loop()->PostTask(FROM_HERE, NewRunnableMethod(
this, &ResourceMessageFilter::DoOnClipboardReadHTML, reply_msg));
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment