| Index: content/browser/renderer_host/clipboard_message_filter.cc
|
| diff --git a/content/browser/renderer_host/clipboard_message_filter.cc b/content/browser/renderer_host/clipboard_message_filter.cc
|
| index 7e46a30d7714faba804ad94e7e13cf3fcd561e47..4ffb80b87cec15c35f48d30e09957c8b9420136c 100644
|
| --- a/content/browser/renderer_host/clipboard_message_filter.cc
|
| +++ b/content/browser/renderer_host/clipboard_message_filter.cc
|
| @@ -4,7 +4,7 @@
|
|
|
| #include "content/browser/renderer_host/clipboard_message_filter.h"
|
|
|
| -#include <memory>
|
| +#include <utility>
|
|
|
| #include "base/bind.h"
|
| #include "base/bind_helpers.h"
|
| @@ -12,11 +12,15 @@
|
| #include "base/macros.h"
|
| #include "base/pickle.h"
|
| #include "base/strings/utf_string_conversions.h"
|
| +#include "base/thread_task_runner_handle.h"
|
| #include "build/build_config.h"
|
| +#include "content/browser/fileapi/chrome_blob_storage_context.h"
|
| #include "content/common/clipboard_messages.h"
|
| +#include "content/public/browser/blob_handle.h"
|
| #include "content/public/browser/browser_context.h"
|
| #include "ipc/ipc_message_macros.h"
|
| #include "third_party/skia/include/core/SkBitmap.h"
|
| +#include "ui/base/clipboard/clipboard.h"
|
| #include "ui/base/clipboard/custom_data_helper.h"
|
| #include "ui/base/clipboard/scoped_clipboard_writer.h"
|
| #include "ui/gfx/codec/png_codec.h"
|
| @@ -31,13 +35,18 @@ void ReleaseSharedMemoryPixels(void* addr, void* context) {
|
| delete reinterpret_cast<base::SharedMemory*>(context);
|
| }
|
|
|
| +// No-op helper for delayed cleanup of BlobHandles generated by reading
|
| +// clipboard images.
|
| +void CleanupReadImageBlob(std::unique_ptr<content::BlobHandle>) {}
|
| +
|
| } // namespace
|
|
|
| -ClipboardMessageFilter::ClipboardMessageFilter()
|
| +ClipboardMessageFilter::ClipboardMessageFilter(
|
| + scoped_refptr<ChromeBlobStorageContext> blob_storage_context)
|
| : BrowserMessageFilter(ClipboardMsgStart),
|
| + blob_storage_context_(std::move(blob_storage_context)),
|
| clipboard_writer_(
|
| - new ui::ScopedClipboardWriter(ui::CLIPBOARD_TYPE_COPY_PASTE)) {
|
| -}
|
| + new ui::ScopedClipboardWriter(ui::CLIPBOARD_TYPE_COPY_PASTE)) {}
|
|
|
| void ClipboardMessageFilter::OverrideThreadForMessage(
|
| const IPC::Message& message, BrowserThread::ID* thread) {
|
| @@ -54,11 +63,6 @@ void ClipboardMessageFilter::OverrideThreadForMessage(
|
| 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) {
|
| @@ -175,34 +179,55 @@ void ClipboardMessageFilter::OnReadImage(ui::ClipboardType type,
|
| IPC::Message* reply_msg) {
|
| SkBitmap bitmap = GetClipboard()->ReadImage(type);
|
|
|
| -#if defined(USE_X11)
|
| + // TODO(dcheng): Just use the worker pool.
|
| BrowserThread::PostTask(
|
| BrowserThread::FILE, FROM_HERE,
|
| - base::Bind(
|
| - &ClipboardMessageFilter::OnReadImageReply, this, bitmap, reply_msg));
|
| -#else
|
| - OnReadImageReply(bitmap, reply_msg);
|
| -#endif
|
| + base::Bind(&ClipboardMessageFilter::ReadAndEncodeImage, this, bitmap,
|
| + reply_msg));
|
| }
|
|
|
| -void ClipboardMessageFilter::OnReadImageReply(
|
| - const SkBitmap& bitmap, IPC::Message* reply_msg) {
|
| - base::SharedMemoryHandle image_handle = base::SharedMemory::NULLHandle();
|
| - uint32_t image_size = 0;
|
| +void ClipboardMessageFilter::ReadAndEncodeImage(const SkBitmap& bitmap,
|
| + IPC::Message* reply_msg) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::FILE);
|
| if (!bitmap.isNull()) {
|
| - std::vector<unsigned char> png_data;
|
| - if (gfx::PNGCodec::FastEncodeBGRASkBitmap(bitmap, false, &png_data)) {
|
| - base::SharedMemory buffer;
|
| - if (buffer.CreateAndMapAnonymous(png_data.size())) {
|
| - memcpy(buffer.memory(), png_data.data(), png_data.size());
|
| - if (buffer.GiveToProcess(PeerHandle(), &image_handle)) {
|
| - image_size = png_data.size();
|
| - }
|
| - }
|
| + std::unique_ptr<std::vector<uint8_t>> png_data(new std::vector<uint8_t>);
|
| + if (gfx::PNGCodec::FastEncodeBGRASkBitmap(bitmap, false, png_data.get())) {
|
| + BrowserThread::PostTask(
|
| + BrowserThread::IO, FROM_HERE,
|
| + base::Bind(&ClipboardMessageFilter::OnReadAndEncodeImageFinished,
|
| + this, base::Passed(&png_data), reply_msg));
|
| + return;
|
| + }
|
| + }
|
| + ClipboardHostMsg_ReadImage::WriteReplyParams(reply_msg, std::string(),
|
| + std::string(), -1);
|
| + Send(reply_msg);
|
| +}
|
| +
|
| +void ClipboardMessageFilter::OnReadAndEncodeImageFinished(
|
| + std::unique_ptr<std::vector<uint8_t>> png_data,
|
| + IPC::Message* reply_msg) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| + if (png_data->size() < std::numeric_limits<uint32_t>::max()) {
|
| + std::unique_ptr<content::BlobHandle> blob_handle =
|
| + blob_storage_context_->CreateMemoryBackedBlob(
|
| + reinterpret_cast<char*>(png_data->data()), png_data->size());
|
| + if (blob_handle) {
|
| + ClipboardHostMsg_ReadImage::WriteReplyParams(
|
| + reply_msg, blob_handle->GetUUID(), ui::Clipboard::kMimeTypePNG,
|
| + static_cast<int64_t>(png_data->size()));
|
| + Send(reply_msg);
|
| + // Give the renderer a minute to pick up a reference to the blob before
|
| + // giving up.
|
| + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
|
| + FROM_HERE,
|
| + base::Bind(&CleanupReadImageBlob, base::Passed(&blob_handle)),
|
| + base::TimeDelta::FromMinutes(1));
|
| + return;
|
| }
|
| }
|
| - ClipboardHostMsg_ReadImage::WriteReplyParams(reply_msg, image_handle,
|
| - image_size);
|
| + ClipboardHostMsg_ReadImage::WriteReplyParams(reply_msg, std::string(),
|
| + std::string(), -1);
|
| Send(reply_msg);
|
| }
|
|
|
|
|