| 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..e317c9e81beccc0dcd4131765ce5eef17ab5ce64 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,16 @@
|
| #include "base/macros.h"
|
| #include "base/pickle.h"
|
| #include "base/strings/utf_string_conversions.h"
|
| +#include "base/thread_task_runner_handle.h"
|
| +#include "base/threading/sequenced_worker_pool.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 +36,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 +64,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 +180,58 @@ void ClipboardMessageFilter::OnReadImage(ui::ClipboardType type,
|
| IPC::Message* reply_msg) {
|
| SkBitmap bitmap = GetClipboard()->ReadImage(type);
|
|
|
| -#if defined(USE_X11)
|
| - BrowserThread::PostTask(
|
| - BrowserThread::FILE, FROM_HERE,
|
| - base::Bind(
|
| - &ClipboardMessageFilter::OnReadImageReply, this, bitmap, reply_msg));
|
| -#else
|
| - OnReadImageReply(bitmap, reply_msg);
|
| -#endif
|
| + BrowserThread::GetBlockingPool()
|
| + ->GetTaskRunnerWithShutdownBehavior(
|
| + base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)
|
| + ->PostTask(FROM_HERE,
|
| + 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) {
|
| 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.
|
| + // TODO(dmurph): There should be a better way of transferring ownership of
|
| + // a blob from the browser to the renderer, rather than relying on this
|
| + // timeout to clean up eventually. See https://crbug.com/604800.
|
| + 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);
|
| }
|
|
|
|
|