Merge from Chromium at DEPS revision r167172
This commit was generated by merge_to_master.py.
Change-Id: Ib8d56fd5ae39a2d7e8c91dcd76cc6d13f25f2aab
diff --git a/content/browser/renderer_host/clipboard_message_filter.cc b/content/browser/renderer_host/clipboard_message_filter.cc
new file mode 100644
index 0000000..d447dc0
--- /dev/null
+++ b/content/browser/renderer_host/clipboard_message_filter.cc
@@ -0,0 +1,257 @@
+// Copyright (c) 2012 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.
+
+#include "content/browser/renderer_host/clipboard_message_filter.h"
+
+#if defined(USE_SYSTEM_ZLIB)
+#include <zlib.h>
+#else
+#include "third_party/zlib/zlib.h"
+#endif
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/stl_util.h"
+#include "content/common/clipboard_messages.h"
+#include "googleurl/src/gurl.h"
+#include "ipc/ipc_message_macros.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/codec/png_codec.h"
+#include "ui/gfx/size.h"
+
+namespace content {
+
+#if defined(OS_WIN)
+
+namespace {
+
+// The write must be performed on the UI thread because the clipboard object
+// from the IO thread cannot create windows so it cannot be the "owner" of the
+// clipboard's contents. // See http://crbug.com/5823.
+void WriteObjectsHelper(const ui::Clipboard::ObjectMap* objects) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ static ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
+ clipboard->WriteObjects(ui::Clipboard::BUFFER_STANDARD, *objects);
+}
+
+} // namespace
+
+#endif
+
+ClipboardMessageFilter::ClipboardMessageFilter() {
+}
+
+void ClipboardMessageFilter::OverrideThreadForMessage(
+ const IPC::Message& message, BrowserThread::ID* thread) {
+ // Clipboard writes should always occur on the UI thread due the restrictions
+ // of various platform APIs. In general, the clipboard is not thread-safe, so
+ // all clipboard calls should be serviced from the UI thread.
+ //
+ // Windows needs clipboard reads to be serviced from the IO thread because
+ // these are sync IPCs which can result in deadlocks with NPAPI plugins if
+ // serviced from the UI thread. Note that Windows clipboard calls ARE
+ // thread-safe so it is ok for reads and writes to be serviced from different
+ // threads.
+#if !defined(OS_WIN)
+ if (IPC_MESSAGE_CLASS(message) == ClipboardMsgStart)
+ *thread = BrowserThread::UI;
+#endif
+
+#if defined(OS_WIN)
+ if (message.type() == ClipboardHostMsg_ReadImage::ID)
+ *thread = BrowserThread::FILE;
+#endif
+}
+
+bool ClipboardMessageFilter::OnMessageReceived(const IPC::Message& message,
+ bool* message_was_ok) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP_EX(ClipboardMessageFilter, message, *message_was_ok)
+ IPC_MESSAGE_HANDLER(ClipboardHostMsg_WriteObjectsAsync, OnWriteObjectsAsync)
+ IPC_MESSAGE_HANDLER(ClipboardHostMsg_WriteObjectsSync, OnWriteObjectsSync)
+ IPC_MESSAGE_HANDLER(ClipboardHostMsg_GetSequenceNumber, OnGetSequenceNumber)
+ IPC_MESSAGE_HANDLER(ClipboardHostMsg_IsFormatAvailable, OnIsFormatAvailable)
+ IPC_MESSAGE_HANDLER(ClipboardHostMsg_Clear, OnClear)
+ IPC_MESSAGE_HANDLER(ClipboardHostMsg_ReadAvailableTypes,
+ OnReadAvailableTypes)
+ IPC_MESSAGE_HANDLER(ClipboardHostMsg_ReadText, OnReadText)
+ IPC_MESSAGE_HANDLER(ClipboardHostMsg_ReadAsciiText, OnReadAsciiText)
+ IPC_MESSAGE_HANDLER(ClipboardHostMsg_ReadHTML, OnReadHTML)
+ IPC_MESSAGE_HANDLER(ClipboardHostMsg_ReadRTF, OnReadRTF)
+ IPC_MESSAGE_HANDLER_DELAY_REPLY(ClipboardHostMsg_ReadImage, OnReadImage)
+ IPC_MESSAGE_HANDLER(ClipboardHostMsg_ReadCustomData, OnReadCustomData)
+ IPC_MESSAGE_HANDLER(ClipboardHostMsg_ReadData, OnReadData)
+#if defined(OS_MACOSX)
+ IPC_MESSAGE_HANDLER(ClipboardHostMsg_FindPboardWriteStringAsync,
+ OnFindPboardWriteString)
+#endif
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+ClipboardMessageFilter::~ClipboardMessageFilter() {
+}
+
+void ClipboardMessageFilter::OnWriteObjectsSync(
+ const ui::Clipboard::ObjectMap& objects,
+ base::SharedMemoryHandle bitmap_handle) {
+ DCHECK(base::SharedMemory::IsHandleValid(bitmap_handle))
+ << "Bad bitmap handle";
+#if defined(OS_WIN)
+ // 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.
+ ui::Clipboard::ObjectMap* long_living_objects =
+ new ui::Clipboard::ObjectMap(objects);
+
+ // Splice the shared memory handle into the clipboard data.
+ ui::Clipboard::ReplaceSharedMemHandle(long_living_objects, bitmap_handle,
+ peer_handle());
+
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&WriteObjectsHelper, base::Owned(long_living_objects)));
+#else
+ // Splice the shared memory handle into the clipboard data.
+ ui::Clipboard::ObjectMap objects_copy(objects);
+ ui::Clipboard::ReplaceSharedMemHandle(&objects_copy,
+ bitmap_handle, peer_handle());
+ GetClipboard()->WriteObjects(ui::Clipboard::BUFFER_STANDARD, objects_copy);
+#endif
+}
+
+void ClipboardMessageFilter::OnWriteObjectsAsync(
+ const ui::Clipboard::ObjectMap& objects) {
+#if defined(OS_WIN)
+ // We cannot write directly from the IO thread, and cannot service the IPC
+ // on the UI thread. We'll copy the relevant data and post a task to preform
+ // the write on the UI thread.
+ ui::Clipboard::ObjectMap* long_living_objects =
+ new ui::Clipboard::ObjectMap(objects);
+
+ // This async message doesn't support shared-memory based bitmaps; they must
+ // be removed otherwise we might dereference a rubbish pointer.
+ long_living_objects->erase(ui::Clipboard::CBF_SMBITMAP);
+
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&WriteObjectsHelper, base::Owned(long_living_objects)));
+#else
+ GetClipboard()->WriteObjects(ui::Clipboard::BUFFER_STANDARD, objects);
+#endif
+}
+
+void ClipboardMessageFilter::OnGetSequenceNumber(
+ ui::Clipboard::Buffer buffer, uint64* sequence_number) {
+ *sequence_number = GetClipboard()->GetSequenceNumber(buffer);
+}
+
+void ClipboardMessageFilter::OnReadAvailableTypes(
+ ui::Clipboard::Buffer buffer, std::vector<string16>* types,
+ bool* contains_filenames) {
+ GetClipboard()->ReadAvailableTypes(buffer, types, contains_filenames);
+}
+
+void ClipboardMessageFilter::OnIsFormatAvailable(
+ const ui::Clipboard::FormatType& format, ui::Clipboard::Buffer buffer,
+ bool* result) {
+ *result = GetClipboard()->IsFormatAvailable(format, buffer);
+}
+
+void ClipboardMessageFilter::OnClear(ui::Clipboard::Buffer buffer) {
+ GetClipboard()->Clear(buffer);
+}
+
+void ClipboardMessageFilter::OnReadText(
+ ui::Clipboard::Buffer buffer, string16* result) {
+ GetClipboard()->ReadText(buffer, result);
+}
+
+void ClipboardMessageFilter::OnReadAsciiText(
+ ui::Clipboard::Buffer buffer, std::string* result) {
+ GetClipboard()->ReadAsciiText(buffer, result);
+}
+
+void ClipboardMessageFilter::OnReadHTML(
+ ui::Clipboard::Buffer buffer, string16* markup, GURL* url,
+ uint32* fragment_start, uint32* fragment_end) {
+ std::string src_url_str;
+ GetClipboard()->ReadHTML(buffer, markup, &src_url_str, fragment_start,
+ fragment_end);
+ *url = GURL(src_url_str);
+}
+
+void ClipboardMessageFilter::OnReadRTF(
+ ui::Clipboard::Buffer buffer, std::string* result) {
+ GetClipboard()->ReadRTF(buffer, result);
+}
+
+void ClipboardMessageFilter::OnReadImage(
+ ui::Clipboard::Buffer buffer, IPC::Message* reply_msg) {
+ SkBitmap bitmap = GetClipboard()->ReadImage(buffer);
+
+#if defined(USE_X11)
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(
+ &ClipboardMessageFilter::OnReadImageReply, this, bitmap, reply_msg));
+#else
+ OnReadImageReply(bitmap, reply_msg);
+#endif
+}
+
+void ClipboardMessageFilter::OnReadImageReply(
+ const SkBitmap& bitmap, IPC::Message* reply_msg) {
+ base::SharedMemoryHandle image_handle = base::SharedMemory::NULLHandle();
+ uint32 image_size = 0;
+ std::string reply_data;
+ if (!bitmap.isNull()) {
+ std::vector<unsigned char> png_data;
+ SkAutoLockPixels lock(bitmap);
+ if (gfx::PNGCodec::EncodeWithCompressionLevel(
+ static_cast<const unsigned char*>(bitmap.getPixels()),
+ gfx::PNGCodec::FORMAT_BGRA,
+ gfx::Size(bitmap.width(), bitmap.height()),
+ bitmap.rowBytes(),
+ false,
+ std::vector<gfx::PNGCodec::Comment>(),
+ Z_BEST_SPEED,
+ &png_data)) {
+ base::SharedMemory buffer;
+ if (buffer.CreateAndMapAnonymous(png_data.size())) {
+ memcpy(buffer.memory(), vector_as_array(&png_data), png_data.size());
+ if (buffer.GiveToProcess(peer_handle(), &image_handle)) {
+ image_size = png_data.size();
+ }
+ }
+ }
+ }
+ ClipboardHostMsg_ReadImage::WriteReplyParams(reply_msg, image_handle,
+ image_size);
+ Send(reply_msg);
+}
+
+void ClipboardMessageFilter::OnReadCustomData(
+ ui::Clipboard::Buffer buffer, const string16& type, string16* result) {
+ GetClipboard()->ReadCustomData(buffer, type, result);
+}
+
+void ClipboardMessageFilter::OnReadData(const ui::Clipboard::FormatType& format,
+ std::string* data) {
+ GetClipboard()->ReadData(format, data);
+}
+
+// static
+ui::Clipboard* ClipboardMessageFilter::GetClipboard() {
+ // We have a static instance of the clipboard service for use by all message
+ // filters. This instance lives for the life of the browser processes.
+ static ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
+ return clipboard;
+}
+
+} // namespace content