diff options
author | rvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-01-31 01:19:57 +0000 |
---|---|---|
committer | rvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-01-31 01:19:57 +0000 |
commit | a92d2fd9d1fe0e74f6ca7d540858a4711b46367e (patch) | |
tree | 3ec4bb1ee681af04ee6757fa65e47b2abd5dff04 /chrome | |
parent | 69b43bdc17d84729fca4e34595e51a88cec099af (diff) | |
download | chromium_src-a92d2fd9d1fe0e74f6ca7d540858a4711b46367e.zip chromium_src-a92d2fd9d1fe0e74f6ca7d540858a4711b46367e.tar.gz chromium_src-a92d2fd9d1fe0e74f6ca7d540858a4711b46367e.tar.bz2 |
Make sure that Clipboard operations that require dispatching
of windows messages are performed on the UI thread.
SetClipboardData requires the clipboard to be open with a handle
to a window that will be notified when the contents are going to
change again. If Windows messages are not processed, any other app
writing to the clipboard will be locked while we acknowledge their
request (by processing the message).
The IO thread doesn't pump windows messages anymore so write
clipboard operations cannot be performed from that thread and have
to be posted to another thread.
BUG=5823
Review URL: http://codereview.chromium.org/19733
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@9003 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/resource_message_filter.cc | 30 |
1 files changed, 29 insertions, 1 deletions
diff --git a/chrome/browser/resource_message_filter.cc b/chrome/browser/resource_message_filter.cc index 63ea64d..dd0dd5a 100644 --- a/chrome/browser/resource_message_filter.cc +++ b/chrome/browser/resource_message_filter.cc @@ -62,6 +62,25 @@ class ContextMenuMessageDispatcher : public Task { DISALLOW_COPY_AND_ASSIGN(ContextMenuMessageDispatcher); }; +// Completes a clipboard write initiated by the renderer. The write must be +// performed on the UI thread because the clipboard service from the IO thread +// cannot create windows so it cannot be the "owner" of the clipboard's +// contents. +class WriteClipboardTask : public Task { + public: + explicit WriteClipboardTask(Clipboard::ObjectMap* objects) + : objects_(objects) {} + ~WriteClipboardTask() {} + + void Run() { + g_browser_process->clipboard_service()->WriteObjects(*objects_.get()); + } + + private: + scoped_ptr<Clipboard::ObjectMap> objects_; +}; + + } // namespace ResourceMessageFilter::ResourceMessageFilter( @@ -445,10 +464,19 @@ void ResourceMessageFilter::OnDownloadUrl(const IPC::Message& message, void ResourceMessageFilter::OnClipboardWriteObjects( const Clipboard::ObjectMap& objects) { + // We cannot write directly from the IO thread, and cannot service the IPC + // on the UI thread. We'll copy the relevant data and get a handle to any + // shared memory so it doesn't go away when we resume the renderer, and post + // a task to perform the write on the UI thread. + Clipboard::ObjectMap* long_living_objects = new Clipboard::ObjectMap(objects); + // We pass the render_handle_ to assist the clipboard with using shared // memory objects. render_handle_ is a handle to the process that would // own any shared memory that might be in the object list. - GetClipboardService()->WriteObjects(objects, render_handle_); + Clipboard::DuplicateRemoteHandles(render_handle_, long_living_objects); + + render_widget_helper_->ui_loop()->PostTask(FROM_HERE, + new WriteClipboardTask(long_living_objects)); } void ResourceMessageFilter::OnClipboardIsFormatAvailable(unsigned int format, |