summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authordcheng <dcheng@chromium.org>2014-11-19 23:16:49 -0800
committerCommit bot <commit-bot@chromium.org>2014-11-20 07:17:08 +0000
commit112adc89f9665f2fd37c1882e1619d183dbbcea0 (patch)
treee9405efba87b9f6da0a49cac9f9e546e261341d6 /content
parent9196d87fcce71cbc79c5c0bb660dc6b0a9d0c670 (diff)
downloadchromium_src-112adc89f9665f2fd37c1882e1619d183dbbcea0.zip
chromium_src-112adc89f9665f2fd37c1882e1619d183dbbcea0.tar.gz
chromium_src-112adc89f9665f2fd37c1882e1619d183dbbcea0.tar.bz2
Reland rewrite clipboard write IPC handling to be easier to understand.
The original implementation sent clipboard data to be written over IPC as a map of clipboard formats to 'parameters' for that format. The parameters were just vectors of byte vectors. Needless to say, this logic was complicated, fragile, and prone to bugs. In the browser process, this resulted in the IPC validation logic being scattered between ClipboardMessageFilter and Clipboard::DispatchObject. The rewrite adds an IPC message for each flavor of data that the renderer is allowed to write to the clipboard. On the browser side, the logic is simply delegated to ScopedClipboardWriter. Since the clipboard object map is no longer under the control of an untrusted process, this allows the removal of a lot of validation logic. Unfortunately, bitmap handling is still a bit complicated because it's sent over shared memory, but all the validation logic has been moved into ClipboardMessageFilter. BUG=319285 TBR=avi@chromium.org,jamesr@chromium.org,wfh@chromium.org Review URL: https://codereview.chromium.org/740763003 Cr-Commit-Position: refs/heads/master@{#304988}
Diffstat (limited to 'content')
-rw-r--r--content/browser/renderer_host/clipboard_message_filter.cc197
-rw-r--r--content/browser/renderer_host/clipboard_message_filter.h35
-rw-r--r--content/browser/renderer_host/clipboard_message_filter_unittest.cc132
-rw-r--r--content/common/clipboard_messages.h40
-rw-r--r--content/content_renderer.gypi6
-rw-r--r--content/content_tests.gypi1
-rw-r--r--content/renderer/clipboard_client.h81
-rw-r--r--content/renderer/renderer_blink_platform_impl.cc6
-rw-r--r--content/renderer/renderer_blink_platform_impl.h4
-rw-r--r--content/renderer/renderer_clipboard_client.cc180
-rw-r--r--content/renderer/renderer_clipboard_client.h43
-rw-r--r--content/renderer/renderer_clipboard_delegate.cc165
-rw-r--r--content/renderer/renderer_clipboard_delegate.h66
-rw-r--r--content/renderer/scoped_clipboard_writer_glue.cc36
-rw-r--r--content/renderer/scoped_clipboard_writer_glue.h30
-rw-r--r--content/renderer/webclipboard_impl.cc105
-rw-r--r--content/renderer/webclipboard_impl.h7
17 files changed, 583 insertions, 551 deletions
diff --git a/content/browser/renderer_host/clipboard_message_filter.cc b/content/browser/renderer_host/clipboard_message_filter.cc
index 3ea8071..af7e616 100644
--- a/content/browser/renderer_host/clipboard_message_filter.cc
+++ b/content/browser/renderer_host/clipboard_message_filter.cc
@@ -7,13 +7,17 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/location.h"
+#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
+#include "base/pickle.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "content/common/clipboard_messages.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/custom_data_helper.h"
+#include "ui/base/clipboard/scoped_clipboard_writer.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/size.h"
#include "url/gurl.h"
@@ -22,38 +26,17 @@ namespace content {
namespace {
-enum BitmapPolicy {
- kFilterBitmap,
- kAllowBitmap,
-};
-void SanitizeObjectMap(ui::Clipboard::ObjectMap* objects,
- BitmapPolicy bitmap_policy) {
- if (bitmap_policy != kAllowBitmap)
- objects->erase(ui::Clipboard::CBF_SMBITMAP);
-
- ui::Clipboard::ObjectMap::iterator data_it =
- objects->find(ui::Clipboard::CBF_DATA);
- if (data_it != objects->end()) {
- const ui::Clipboard::FormatType& web_custom_format =
- ui::Clipboard::GetWebCustomDataFormatType();
- if (data_it->second.size() != 2 ||
- !web_custom_format.Equals(
- ui::Clipboard::FormatType::Deserialize(std::string(
- &data_it->second[0].front(),
- data_it->second[0].size())))) {
- // CBF_DATA should always have two parameters associated with it, and the
- // associated FormatType should always be web custom data. If not, then
- // data is malformed and we'll ignore it.
- objects->erase(ui::Clipboard::CBF_DATA);
- }
- }
+void ReleaseSharedMemoryPixels(void* addr, void* context) {
+ delete reinterpret_cast<base::SharedMemory*>(context);
}
} // namespace
-
ClipboardMessageFilter::ClipboardMessageFilter()
- : BrowserMessageFilter(ClipboardMsgStart) {}
+ : BrowserMessageFilter(ClipboardMsgStart),
+ clipboard_writer_(
+ new ui::ScopedClipboardWriter(ui::CLIPBOARD_TYPE_COPY_PASTE)) {
+}
void ClipboardMessageFilter::OverrideThreadForMessage(
const IPC::Message& message, BrowserThread::ID* thread) {
@@ -80,8 +63,6 @@ void ClipboardMessageFilter::OverrideThreadForMessage(
bool ClipboardMessageFilter::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(ClipboardMessageFilter, message)
- 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)
@@ -92,6 +73,14 @@ bool ClipboardMessageFilter::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(ClipboardHostMsg_ReadRTF, OnReadRTF)
IPC_MESSAGE_HANDLER_DELAY_REPLY(ClipboardHostMsg_ReadImage, OnReadImage)
IPC_MESSAGE_HANDLER(ClipboardHostMsg_ReadCustomData, OnReadCustomData)
+ IPC_MESSAGE_HANDLER(ClipboardHostMsg_WriteText, OnWriteText)
+ IPC_MESSAGE_HANDLER(ClipboardHostMsg_WriteHTML, OnWriteHTML)
+ IPC_MESSAGE_HANDLER(ClipboardHostMsg_WriteSmartPasteMarker,
+ OnWriteSmartPasteMarker)
+ IPC_MESSAGE_HANDLER(ClipboardHostMsg_WriteCustomData, OnWriteCustomData)
+ IPC_MESSAGE_HANDLER(ClipboardHostMsg_WriteBookmark, OnWriteBookmark)
+ IPC_MESSAGE_HANDLER(ClipboardHostMsg_WriteImage, OnWriteImage)
+ IPC_MESSAGE_HANDLER(ClipboardHostMsg_CommitWrite, OnCommitWrite);
#if defined(OS_MACOSX)
IPC_MESSAGE_HANDLER(ClipboardHostMsg_FindPboardWriteStringAsync,
OnFindPboardWriteString)
@@ -104,71 +93,6 @@ bool ClipboardMessageFilter::OnMessageReceived(const IPC::Message& message) {
ClipboardMessageFilter::~ClipboardMessageFilter() {
}
-void ClipboardMessageFilter::OnWriteObjectsSync(
- const ui::Clipboard::ObjectMap& objects,
- base::SharedMemoryHandle bitmap_handle) {
- DCHECK(base::SharedMemory::IsHandleValid(bitmap_handle))
- << "Bad bitmap handle";
-
- // On Windows, we can't write directly from the IO thread, so we copy the data
- // into a heap allocated map and post a task to the UI thread. On other
- // platforms, to lower the amount of time the renderer has to wait for the
- // sync IPC to complete, we also take a copy and post a task to flush the data
- // to the clipboard later.
- scoped_ptr<ui::Clipboard::ObjectMap> long_living_objects(
- new ui::Clipboard::ObjectMap(objects));
- SanitizeObjectMap(long_living_objects.get(), kAllowBitmap);
- // Splice the shared memory handle into the data. |long_living_objects| now
- // contains a heap-allocated SharedMemory object that references
- // |bitmap_handle|. This reference will keep the shared memory section alive
- // when this IPC returns, and the SharedMemory object will eventually be
- // freed by ui::Clipboard::WriteObjects().
- if (!ui::Clipboard::ReplaceSharedMemHandle(
- long_living_objects.get(), bitmap_handle, PeerHandle()))
- return;
-
- BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&ClipboardMessageFilter::WriteObjectsOnUIThread,
- base::Owned(long_living_objects.release())));
-}
-
-// On Windows, 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.
-// TODO(dcheng): Temporarily a member of ClipboardMessageFilter so it can access
-// ui::Clipboard::WriteObjects().
-void ClipboardMessageFilter::WriteObjectsOnUIThread(
- const ui::Clipboard::ObjectMap* objects) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- static ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
- clipboard->WriteObjects(ui::CLIPBOARD_TYPE_COPY_PASTE, *objects);
-}
-
-void ClipboardMessageFilter::OnWriteObjectsAsync(
- const 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.
- scoped_ptr<ui::Clipboard::ObjectMap> sanitized_objects(
- new ui::Clipboard::ObjectMap(objects));
- SanitizeObjectMap(sanitized_objects.get(), kFilterBitmap);
-
-#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.
- BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(
- &WriteObjectsOnUIThread, base::Owned(sanitized_objects.release())));
-#else
- GetClipboard()->WriteObjects(
- ui::CLIPBOARD_TYPE_COPY_PASTE, *sanitized_objects.get());
-#endif
-}
-
void ClipboardMessageFilter::OnGetSequenceNumber(ui::ClipboardType type,
uint64* sequence_number) {
*sequence_number = GetClipboard()->GetSequenceNumber(type);
@@ -286,6 +210,91 @@ void ClipboardMessageFilter::OnReadCustomData(ui::ClipboardType clipboard_type,
GetClipboard()->ReadCustomData(clipboard_type, type, result);
}
+void ClipboardMessageFilter::OnWriteText(ui::ClipboardType clipboard_type,
+ const base::string16& text) {
+ clipboard_writer_->WriteText(text);
+}
+
+void ClipboardMessageFilter::OnWriteHTML(ui::ClipboardType clipboard_type,
+ const base::string16& markup,
+ const GURL& url) {
+ clipboard_writer_->WriteHTML(markup, url.spec());
+}
+
+void ClipboardMessageFilter::OnWriteSmartPasteMarker(
+ ui::ClipboardType clipboard_type) {
+ clipboard_writer_->WriteWebSmartPaste();
+}
+
+void ClipboardMessageFilter::OnWriteCustomData(
+ ui::ClipboardType clipboard_type,
+ const std::map<base::string16, base::string16>& data) {
+ Pickle pickle;
+ ui::WriteCustomDataToPickle(data, &pickle);
+ clipboard_writer_->WritePickledData(
+ pickle, ui::Clipboard::GetWebCustomDataFormatType());
+}
+
+void ClipboardMessageFilter::OnWriteBookmark(ui::ClipboardType clipboard_type,
+ const GURL& url,
+ const base::string16& title) {
+ clipboard_writer_->WriteBookmark(title, url.spec());
+}
+
+void ClipboardMessageFilter::OnWriteImage(ui::ClipboardType clipboard_type,
+ const gfx::Size& size,
+ base::SharedMemoryHandle handle) {
+ if (!base::SharedMemory::IsHandleValid(handle)) {
+ return;
+ }
+
+ scoped_ptr<base::SharedMemory> bitmap_buffer(
+#if defined(OS_WIN)
+ new base::SharedMemory(handle, true, PeerHandle()));
+#else
+ new base::SharedMemory(handle, true));
+#endif
+
+ SkBitmap bitmap;
+ // Let Skia do some sanity checking for (no negative widths/heights, no
+ // overflows while calculating bytes per row, etc).
+ if (!bitmap.setInfo(
+ SkImageInfo::MakeN32Premul(size.width(), size.height()))) {
+ return;
+ }
+
+ // Make sure the size is representable as a signed 32-bit int, so
+ // SkBitmap::getSize() won't be truncated.
+ if (!sk_64_isS32(bitmap.computeSize64()))
+ return;
+
+ if (!bitmap_buffer->Map(bitmap.getSize()))
+ return;
+
+ if (!bitmap.installPixels(bitmap.info(), bitmap_buffer->memory(),
+ bitmap.rowBytes(), NULL, &ReleaseSharedMemoryPixels,
+ bitmap_buffer.get()))
+ return;
+
+ // On success, SkBitmap now owns the SharedMemory.
+ ignore_result(bitmap_buffer.release());
+ clipboard_writer_->WriteImage(bitmap);
+}
+
+void ClipboardMessageFilter::OnCommitWrite(ui::ClipboardType clipboard_type) {
+#if defined(OS_WIN)
+ // On non-Windows platforms, all clipboard IPCs are handled on the UI thread.
+ // However, Windows handles the clipboard IPCs on the IO thread to prevent
+ // deadlocks. Clipboard writes must still occur 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.
+ BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE,
+ clipboard_writer_.release());
+#endif
+ clipboard_writer_.reset(
+ new ui::ScopedClipboardWriter(ui::CLIPBOARD_TYPE_COPY_PASTE));
+}
+
// static
ui::Clipboard* ClipboardMessageFilter::GetClipboard() {
// We have a static instance of the clipboard service for use by all message
diff --git a/content/browser/renderer_host/clipboard_message_filter.h b/content/browser/renderer_host/clipboard_message_filter.h
index 792bfc5..3f01e86 100644
--- a/content/browser/renderer_host/clipboard_message_filter.h
+++ b/content/browser/renderer_host/clipboard_message_filter.h
@@ -9,15 +9,23 @@
#include <vector>
#include "base/basictypes.h"
+#include "base/memory/shared_memory.h"
#include "content/common/clipboard_format.h"
+#include "content/common/content_export.h"
#include "content/public/browser/browser_message_filter.h"
#include "ui/base/clipboard/clipboard.h"
class GURL;
+namespace ui {
+class ScopedClipboardWriter;
+} // namespace ui
+
namespace content {
-class ClipboardMessageFilter : public BrowserMessageFilter {
+class ClipboardMessageFilterTest;
+
+class CONTENT_EXPORT ClipboardMessageFilter : public BrowserMessageFilter {
public:
ClipboardMessageFilter();
@@ -26,12 +34,9 @@ class ClipboardMessageFilter : public BrowserMessageFilter {
bool OnMessageReceived(const IPC::Message& message) override;
private:
- ~ClipboardMessageFilter() override;
+ friend class ClipboardMessageFilterTest;
- void OnWriteObjectsAsync(const ui::Clipboard::ObjectMap& objects);
- void OnWriteObjectsSync(const ui::Clipboard::ObjectMap& objects,
- base::SharedMemoryHandle bitmap_handle);
- static void WriteObjectsOnUIThread(const ui::Clipboard::ObjectMap* objects);
+ ~ClipboardMessageFilter() override;
void OnGetSequenceNumber(const ui::ClipboardType type,
uint64* sequence_number);
@@ -57,6 +62,22 @@ class ClipboardMessageFilter : public BrowserMessageFilter {
void OnReadData(const ui::Clipboard::FormatType& format,
std::string* data);
+ void OnWriteText(ui::ClipboardType clipboard_type,
+ const base::string16& text);
+ void OnWriteHTML(ui::ClipboardType clipboard_type,
+ const base::string16& markup,
+ const GURL& url);
+ void OnWriteSmartPasteMarker(ui::ClipboardType clipboard_type);
+ void OnWriteCustomData(ui::ClipboardType clipboard_type,
+ const std::map<base::string16, base::string16>& data);
+ void OnWriteBookmark(ui::ClipboardType clipboard_type,
+ const GURL& url,
+ const base::string16& title);
+ void OnWriteImage(ui::ClipboardType clipboard_type,
+ const gfx::Size& size,
+ base::SharedMemoryHandle handle);
+ void OnCommitWrite(ui::ClipboardType clipboard_type);
+
#if defined(OS_MACOSX)
void OnFindPboardWriteString(const base::string16& text);
#endif
@@ -67,6 +88,8 @@ class ClipboardMessageFilter : public BrowserMessageFilter {
// thread.
static ui::Clipboard* GetClipboard();
+ scoped_ptr<ui::ScopedClipboardWriter> clipboard_writer_;
+
DISALLOW_COPY_AND_ASSIGN(ClipboardMessageFilter);
};
diff --git a/content/browser/renderer_host/clipboard_message_filter_unittest.cc b/content/browser/renderer_host/clipboard_message_filter_unittest.cc
new file mode 100644
index 0000000..70761b7
--- /dev/null
+++ b/content/browser/renderer_host/clipboard_message_filter_unittest.cc
@@ -0,0 +1,132 @@
+// Copyright 2014 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"
+
+#include <string.h>
+
+#include "base/memory/ref_counted.h"
+#include "base/process/process_handle.h"
+#include "base/run_loop.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/test/test_clipboard.h"
+#include "ui/gfx/size.h"
+
+namespace content {
+
+class ClipboardMessageFilterTest : public ::testing::Test {
+ protected:
+ ClipboardMessageFilterTest()
+ : filter_(new ClipboardMessageFilter),
+ clipboard_(ui::TestClipboard::CreateForCurrentThread()) {
+ filter_->set_peer_pid_for_testing(base::GetCurrentProcId());
+ }
+
+ virtual ~ClipboardMessageFilterTest() override {
+ ui::Clipboard::DestroyClipboardForCurrentThread();
+ }
+
+ scoped_ptr<base::SharedMemory> CreateAndMapReadOnlySharedMemory(size_t size) {
+ scoped_ptr<base::SharedMemory> m = CreateReadOnlySharedMemory(size);
+ if (!m->Map(size))
+ return nullptr;
+ return m;
+ }
+
+ scoped_ptr<base::SharedMemory> CreateReadOnlySharedMemory(size_t size) {
+ scoped_ptr<base::SharedMemory> m(new base::SharedMemory());
+ base::SharedMemoryCreateOptions options;
+ options.size = size;
+ options.share_read_only = true;
+ if (!m->Create(options))
+ return nullptr;
+ return m;
+ }
+
+ void CallWriteImage(const gfx::Size& size,
+ base::SharedMemory* shared_memory) {
+ base::SharedMemoryHandle handle;
+ ASSERT_TRUE(shared_memory->GiveReadOnlyToProcess(
+ base::GetCurrentProcessHandle(), &handle));
+ CallWriteImageDirectly(size, handle);
+ }
+
+ // Prefer to use CallWriteImage() in tests.
+ void CallWriteImageDirectly(const gfx::Size& size,
+ base::SharedMemoryHandle handle) {
+ filter_->OnWriteImage(ui::CLIPBOARD_TYPE_COPY_PASTE, size, handle);
+ }
+
+ void CallCommitWrite() {
+ filter_->OnCommitWrite(ui::CLIPBOARD_TYPE_COPY_PASTE);
+ base::RunLoop().RunUntilIdle();
+ }
+
+ ui::Clipboard* clipboard() { return clipboard_; }
+
+ private:
+ const TestBrowserThreadBundle thread_bundle_;
+ const scoped_refptr<ClipboardMessageFilter> filter_;
+ ui::Clipboard* const clipboard_;
+};
+
+// Test that it actually works.
+TEST_F(ClipboardMessageFilterTest, SimpleImage) {
+ static const uint32_t bitmap_data[] = {
+ 0x33333333, 0xdddddddd, 0xeeeeeeee, 0x00000000,
+ 0x88888888, 0x66666666, 0x55555555, 0xbbbbbbbb,
+ 0x44444444, 0xaaaaaaaa, 0x99999999, 0x77777777,
+ 0xffffffff, 0x11111111, 0x22222222, 0xcccccccc,
+ };
+
+ scoped_ptr<base::SharedMemory> shared_memory =
+ CreateAndMapReadOnlySharedMemory(sizeof(bitmap_data));
+ memcpy(shared_memory->memory(), bitmap_data, sizeof(bitmap_data));
+
+ CallWriteImage(gfx::Size(4, 4), shared_memory.get());
+ uint64_t sequence_number =
+ clipboard()->GetSequenceNumber(ui::CLIPBOARD_TYPE_COPY_PASTE);
+ CallCommitWrite();
+
+ EXPECT_NE(sequence_number,
+ clipboard()->GetSequenceNumber(ui::CLIPBOARD_TYPE_COPY_PASTE));
+ EXPECT_FALSE(clipboard()->IsFormatAvailable(
+ ui::Clipboard::GetPlainTextFormatType(), ui::CLIPBOARD_TYPE_COPY_PASTE));
+ EXPECT_TRUE(clipboard()->IsFormatAvailable(
+ ui::Clipboard::GetBitmapFormatType(), ui::CLIPBOARD_TYPE_COPY_PASTE));
+
+ SkBitmap actual = clipboard()->ReadImage(ui::CLIPBOARD_TYPE_COPY_PASTE);
+ SkAutoLockPixels locked(actual);
+ EXPECT_EQ(sizeof(bitmap_data), actual.getSize());
+ EXPECT_EQ(0,
+ memcmp(bitmap_data, actual.getAddr32(0, 0), sizeof(bitmap_data)));
+}
+
+// Test with a size that would overflow a naive 32-bit row bytes calculation.
+TEST_F(ClipboardMessageFilterTest, ImageSizeOverflows32BitRowBytes) {
+ scoped_ptr<base::SharedMemory> shared_memory =
+ CreateReadOnlySharedMemory(0x20000000);
+
+ CallWriteImage(gfx::Size(0x20000000, 1), shared_memory.get());
+ uint64_t sequence_number =
+ clipboard()->GetSequenceNumber(ui::CLIPBOARD_TYPE_COPY_PASTE);
+ CallCommitWrite();
+
+ EXPECT_EQ(sequence_number,
+ clipboard()->GetSequenceNumber(ui::CLIPBOARD_TYPE_COPY_PASTE));
+}
+
+TEST_F(ClipboardMessageFilterTest, InvalidSharedMemoryHandle) {
+ CallWriteImageDirectly(gfx::Size(5, 5), base::SharedMemory::NULLHandle());
+ uint64_t sequence_number =
+ clipboard()->GetSequenceNumber(ui::CLIPBOARD_TYPE_COPY_PASTE);
+ CallCommitWrite();
+
+ EXPECT_EQ(sequence_number,
+ clipboard()->GetSequenceNumber(ui::CLIPBOARD_TYPE_COPY_PASTE));
+}
+
+} // namespace content
diff --git a/content/common/clipboard_messages.h b/content/common/clipboard_messages.h
index add55e4..ff02524 100644
--- a/content/common/clipboard_messages.h
+++ b/content/common/clipboard_messages.h
@@ -4,10 +4,12 @@
// Multiply-included message file, so no include guard.
+#include <map>
#include <string>
#include <vector>
#include "base/memory/shared_memory.h"
+#include "base/strings/string16.h"
#include "content/common/clipboard_format.h"
#include "content/public/common/common_param_traits.h"
#include "ipc/ipc_message_macros.h"
@@ -21,15 +23,6 @@ IPC_ENUM_TRAITS_MAX_VALUE(ui::ClipboardType, ui::CLIPBOARD_TYPE_LAST)
// Clipboard IPC messages sent from the renderer to the browser.
-// This message is used when the object list does not contain a bitmap.
-IPC_MESSAGE_CONTROL1(ClipboardHostMsg_WriteObjectsAsync,
- ui::Clipboard::ObjectMap /* objects */)
-// This message is used when the object list contains a bitmap.
-// It is synchronized so that the renderer knows when it is safe to
-// free the shared memory used to transfer the bitmap.
-IPC_SYNC_MESSAGE_CONTROL2_0(ClipboardHostMsg_WriteObjectsSync,
- ui::Clipboard::ObjectMap /* objects */,
- base::SharedMemoryHandle /* bitmap handle */)
IPC_SYNC_MESSAGE_CONTROL1_1(ClipboardHostMsg_GetSequenceNumber,
ui::ClipboardType /* type */,
uint64 /* result */)
@@ -64,6 +57,35 @@ IPC_SYNC_MESSAGE_CONTROL2_1(ClipboardHostMsg_ReadCustomData,
base::string16 /* type */,
base::string16 /* result */)
+// Writing to the clipboard via IPC is a two-phase operation. First, the sender
+// sends the different types of data it'd like to write to the receiver. Then,
+// it sends a commit message to commit the data to the system clipboard.
+IPC_MESSAGE_CONTROL2(ClipboardHostMsg_WriteText,
+ ui::ClipboardType /* type */,
+ base::string16 /* text */)
+IPC_MESSAGE_CONTROL3(ClipboardHostMsg_WriteHTML,
+ ui::ClipboardType /* type */,
+ base::string16 /* markup */,
+ GURL /* url */)
+IPC_MESSAGE_CONTROL1(ClipboardHostMsg_WriteSmartPasteMarker,
+ ui::ClipboardType /* type */);
+// Custom data consists of arbitrary MIME types an untrusted sender wants to
+// write to the clipboard. Note that exposing a general interface to do this is
+// dangerous--an untrusted sender could cause a DoS or code execution.
+typedef std::map<base::string16, base::string16> CustomDataMap;
+IPC_MESSAGE_CONTROL2(ClipboardHostMsg_WriteCustomData,
+ ui::ClipboardType /* type */,
+ CustomDataMap /* custom data */)
+IPC_MESSAGE_CONTROL3(ClipboardHostMsg_WriteBookmark,
+ ui::ClipboardType /* type */,
+ GURL /* url */,
+ base::string16 /* title */)
+IPC_SYNC_MESSAGE_CONTROL3_0(ClipboardHostMsg_WriteImage,
+ ui::ClipboardType /* type */,
+ gfx::Size /* size */,
+ base::SharedMemoryHandle /* bitmap handle */)
+IPC_MESSAGE_CONTROL1(ClipboardHostMsg_CommitWrite, ui::ClipboardType /* type */)
+
#if defined(OS_MACOSX)
IPC_MESSAGE_CONTROL1(ClipboardHostMsg_FindPboardWriteStringAsync,
base::string16 /* text */)
diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi
index 6518e02..18a6fca 100644
--- a/content/content_renderer.gypi
+++ b/content/content_renderer.gypi
@@ -332,8 +332,8 @@
'renderer/render_widget_fullscreen.h',
'renderer/renderer_blink_platform_impl.cc',
'renderer/renderer_blink_platform_impl.h',
- 'renderer/renderer_clipboard_client.cc',
- 'renderer/renderer_clipboard_client.h',
+ 'renderer/renderer_clipboard_delegate.cc',
+ 'renderer/renderer_clipboard_delegate.h',
'renderer/renderer_main.cc',
'renderer/renderer_main_platform_delegate.h',
'renderer/renderer_main_platform_delegate_android.cc',
@@ -371,8 +371,6 @@
'renderer/screen_orientation/screen_orientation_dispatcher.h',
'renderer/screen_orientation/screen_orientation_observer.cc',
'renderer/screen_orientation/screen_orientation_observer.h',
- 'renderer/scoped_clipboard_writer_glue.cc',
- 'renderer/scoped_clipboard_writer_glue.h',
'renderer/service_worker/embedded_worker_context_client.cc',
'renderer/service_worker/embedded_worker_context_client.h',
'renderer/service_worker/embedded_worker_context_message_filter.cc',
diff --git a/content/content_tests.gypi b/content/content_tests.gypi
index 906493f..1645996 100644
--- a/content/content_tests.gypi
+++ b/content/content_tests.gypi
@@ -571,6 +571,7 @@
'browser/quota/quota_temporary_storage_evictor_unittest.cc',
'browser/quota/storage_monitor_unittest.cc',
'browser/quota/usage_tracker_unittest.cc',
+ 'browser/renderer_host/clipboard_message_filter_unittest.cc',
'browser/renderer_host/input/gesture_event_queue_unittest.cc',
'browser/renderer_host/input/gesture_text_selector_unittest.cc',
'browser/renderer_host/input/input_router_impl_unittest.cc',
diff --git a/content/renderer/clipboard_client.h b/content/renderer/clipboard_client.h
deleted file mode 100644
index 7f1b2dc..0000000
--- a/content/renderer/clipboard_client.h
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright (c) 2013 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.
-
-#ifndef CONTENT_RENDERER_CLIPBOARD_CLIENT_H_
-#define CONTENT_RENDERER_CLIPBOARD_CLIENT_H_
-
-#include "content/common/clipboard_format.h"
-#include "ui/base/clipboard/clipboard.h"
-
-class GURL;
-
-namespace content {
-
-// Interface for the content embedder to implement to support clipboard.
-class ClipboardClient {
- public:
- class WriteContext {
- public:
- virtual ~WriteContext() { }
-
- // Writes bitmap data into the context, updating the ObjectMap.
- virtual void WriteBitmapFromPixels(ui::Clipboard::ObjectMap* objects,
- const void* pixels,
- const gfx::Size& size) = 0;
-
- // Flushes all gathered data.
- virtual void Flush(const ui::Clipboard::ObjectMap& objects) = 0;
- };
-
- virtual ~ClipboardClient() { }
-
- // Get a clipboard that can be used to construct a ScopedClipboardWriterGlue.
- virtual ui::Clipboard* GetClipboard() = 0;
-
- // Get a sequence number which uniquely identifies clipboard state.
- virtual uint64 GetSequenceNumber(ui::ClipboardType type) = 0;
-
- // Tests whether the clipboard contains a certain format
- virtual bool IsFormatAvailable(ClipboardFormat format,
- ui::ClipboardType type) = 0;
-
- // Clear the contents of the clipboard.
- virtual void Clear(ui::ClipboardType type) = 0;
-
- // Reads the available types from the clipboard, if available.
- virtual void ReadAvailableTypes(ui::ClipboardType type,
- std::vector<base::string16>* types,
- bool* contains_filenames) = 0;
-
- // Reads text from the clipboard, trying UNICODE first, then falling back to
- // ASCII.
- virtual void ReadText(ui::ClipboardType type,
- base::string16* result) = 0;
-
- // Reads HTML from the clipboard, if available.
- virtual void ReadHTML(ui::ClipboardType type,
- base::string16* markup,
- GURL* url,
- uint32* fragment_start,
- uint32* fragment_end) = 0;
-
- // Reads RTF from the clipboard, if available.
- virtual void ReadRTF(ui::ClipboardType type, std::string* result) = 0;
-
- // Reads and image from the clipboard, if available.
- virtual void ReadImage(ui::ClipboardType type, std::string* data) = 0;
-
- // Reads a custom data type from the clipboard, if available.
- virtual void ReadCustomData(ui::ClipboardType clipboard_type,
- const base::string16& type,
- base::string16* data) = 0;
-
- // Creates a context to write clipboard data. May return NULL.
- virtual WriteContext* CreateWriteContext() = 0;
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_CLIPBOARD_CLIENT_H_
-
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc
index 29a519d..9ff5b4f 100644
--- a/content/renderer/renderer_blink_platform_impl.cc
+++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -48,7 +48,7 @@
#include "content/renderer/media/renderer_webaudiodevice_impl.h"
#include "content/renderer/media/renderer_webmidiaccessor_impl.h"
#include "content/renderer/render_thread_impl.h"
-#include "content/renderer/renderer_clipboard_client.h"
+#include "content/renderer/renderer_clipboard_delegate.h"
#include "content/renderer/scheduler/renderer_scheduler.h"
#include "content/renderer/scheduler/web_scheduler_impl.h"
#include "content/renderer/screen_orientation/screen_orientation_observer.h"
@@ -231,8 +231,8 @@ RendererBlinkPlatformImpl::RendererBlinkPlatformImpl(
RendererScheduler* renderer_scheduler)
: BlinkPlatformImpl(renderer_scheduler->DefaultTaskRunner()),
web_scheduler_(new WebSchedulerImpl(renderer_scheduler)),
- clipboard_client_(new RendererClipboardClient),
- clipboard_(new WebClipboardImpl(clipboard_client_.get())),
+ clipboard_delegate_(new RendererClipboardDelegate),
+ clipboard_(new WebClipboardImpl(clipboard_delegate_.get())),
mime_registry_(new RendererBlinkPlatformImpl::MimeRegistry),
sudden_termination_disables_(0),
plugin_refresh_allowed_(true),
diff --git a/content/renderer/renderer_blink_platform_impl.h b/content/renderer/renderer_blink_platform_impl.h
index 493bec7..cfa2512 100644
--- a/content/renderer/renderer_blink_platform_impl.h
+++ b/content/renderer/renderer_blink_platform_impl.h
@@ -42,7 +42,7 @@ class DeviceMotionEventPump;
class DeviceOrientationEventPump;
class PlatformEventObserverBase;
class QuotaMessageFilter;
-class RendererClipboardClient;
+class RendererClipboardDelegate;
class RendererScheduler;
class RenderView;
class ThreadSafeSender;
@@ -206,7 +206,7 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
scoped_ptr<WebSchedulerImpl> web_scheduler_;
- scoped_ptr<RendererClipboardClient> clipboard_client_;
+ scoped_ptr<RendererClipboardDelegate> clipboard_delegate_;
scoped_ptr<WebClipboardImpl> clipboard_;
class FileUtilities;
diff --git a/content/renderer/renderer_clipboard_client.cc b/content/renderer/renderer_clipboard_client.cc
deleted file mode 100644
index 1e2953e..0000000
--- a/content/renderer/renderer_clipboard_client.cc
+++ /dev/null
@@ -1,180 +0,0 @@
-// 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.
-
-// This file provides the embedder's side of the Clipboard interface.
-
-#include "content/renderer/renderer_clipboard_client.h"
-
-#include "base/memory/shared_memory.h"
-#include "base/numerics/safe_math.h"
-#include "base/strings/string16.h"
-#include "content/common/clipboard_messages.h"
-#include "content/public/renderer/content_renderer_client.h"
-#include "content/renderer/render_thread_impl.h"
-#include "content/renderer/scoped_clipboard_writer_glue.h"
-#include "ui/base/clipboard/clipboard.h"
-#include "ui/gfx/size.h"
-
-namespace content {
-
-namespace {
-
-class RendererClipboardWriteContext : public ClipboardClient::WriteContext {
- public:
- RendererClipboardWriteContext();
- ~RendererClipboardWriteContext() override;
- void WriteBitmapFromPixels(ui::Clipboard::ObjectMap* objects,
- const void* pixels,
- const gfx::Size& size) override;
- void Flush(const ui::Clipboard::ObjectMap& objects) override;
-
- private:
- scoped_ptr<base::SharedMemory> shared_buf_;
- DISALLOW_COPY_AND_ASSIGN(RendererClipboardWriteContext);
-};
-
-RendererClipboardWriteContext::RendererClipboardWriteContext() {
-}
-
-RendererClipboardWriteContext::~RendererClipboardWriteContext() {
-}
-
-// This definition of WriteBitmapFromPixels uses shared memory to communicate
-// across processes.
-void RendererClipboardWriteContext::WriteBitmapFromPixels(
- ui::Clipboard::ObjectMap* objects,
- const void* pixels,
- const gfx::Size& size) {
- // Do not try to write a bitmap more than once
- if (shared_buf_)
- return;
-
- base::CheckedNumeric<uint32> checked_buf_size = 4;
- checked_buf_size *= size.width();
- checked_buf_size *= size.height();
- if (!checked_buf_size.IsValid())
- return;
-
- uint32 buf_size = checked_buf_size.ValueOrDie();
-
- // Allocate a shared memory buffer to hold the bitmap bits.
- shared_buf_.reset(ChildThread::current()->AllocateSharedMemory(buf_size));
- if (!shared_buf_)
- return;
-
- // Copy the bits into shared memory
- DCHECK(shared_buf_->memory());
- memcpy(shared_buf_->memory(), pixels, buf_size);
- shared_buf_->Unmap();
-
- ui::Clipboard::ObjectMapParam size_param;
- const char* size_data = reinterpret_cast<const char*>(&size);
- for (size_t i = 0; i < sizeof(gfx::Size); ++i)
- size_param.push_back(size_data[i]);
-
- ui::Clipboard::ObjectMapParams params;
-
- // The first parameter is replaced on the receiving end with a pointer to
- // a shared memory object containing the bitmap. We reserve space for it here.
- ui::Clipboard::ObjectMapParam place_holder_param;
- params.push_back(place_holder_param);
- params.push_back(size_param);
- (*objects)[ui::Clipboard::CBF_SMBITMAP] = params;
-}
-
-// Flushes the objects to the clipboard with an IPC.
-void RendererClipboardWriteContext::Flush(
- const ui::Clipboard::ObjectMap& objects) {
- if (shared_buf_) {
- RenderThreadImpl::current()->Send(
- new ClipboardHostMsg_WriteObjectsSync(objects, shared_buf_->handle()));
- } else {
- RenderThreadImpl::current()->Send(
- new ClipboardHostMsg_WriteObjectsAsync(objects));
- }
-}
-
-} // anonymous namespace
-
-RendererClipboardClient::RendererClipboardClient() {
-}
-
-RendererClipboardClient::~RendererClipboardClient() {
-}
-
-ui::Clipboard* RendererClipboardClient::GetClipboard() {
- return NULL;
-}
-
-uint64 RendererClipboardClient::GetSequenceNumber(ui::ClipboardType type) {
- uint64 sequence_number = 0;
- RenderThreadImpl::current()->Send(
- new ClipboardHostMsg_GetSequenceNumber(type, &sequence_number));
- return sequence_number;
-}
-
-bool RendererClipboardClient::IsFormatAvailable(content::ClipboardFormat format,
- ui::ClipboardType type) {
- bool result = false;
- RenderThreadImpl::current()->Send(
- new ClipboardHostMsg_IsFormatAvailable(format, type, &result));
- return result;
-}
-
-void RendererClipboardClient::Clear(ui::ClipboardType type) {
- RenderThreadImpl::current()->Send(new ClipboardHostMsg_Clear(type));
-}
-
-void RendererClipboardClient::ReadAvailableTypes(
- ui::ClipboardType type,
- std::vector<base::string16>* types,
- bool* contains_filenames) {
- RenderThreadImpl::current()->Send(new ClipboardHostMsg_ReadAvailableTypes(
- type, types, contains_filenames));
-}
-
-void RendererClipboardClient::ReadText(ui::ClipboardType type,
- base::string16* result) {
- RenderThreadImpl::current()->Send(
- new ClipboardHostMsg_ReadText(type, result));
-}
-
-void RendererClipboardClient::ReadHTML(ui::ClipboardType type,
- base::string16* markup,
- GURL* url, uint32* fragment_start,
- uint32* fragment_end) {
- RenderThreadImpl::current()->Send(new ClipboardHostMsg_ReadHTML(
- type, markup, url, fragment_start, fragment_end));
-}
-
-void RendererClipboardClient::ReadRTF(ui::ClipboardType type,
- std::string* result) {
- RenderThreadImpl::current()->Send(new ClipboardHostMsg_ReadRTF(type, result));
-}
-
-void RendererClipboardClient::ReadImage(ui::ClipboardType type,
- std::string* data) {
- base::SharedMemoryHandle image_handle;
- uint32 image_size = 0;
- RenderThreadImpl::current()->Send(
- new ClipboardHostMsg_ReadImage(type, &image_handle, &image_size));
- if (base::SharedMemory::IsHandleValid(image_handle)) {
- base::SharedMemory buffer(image_handle, true);
- buffer.Map(image_size);
- data->append(static_cast<char*>(buffer.memory()), image_size);
- }
-}
-
-void RendererClipboardClient::ReadCustomData(ui::ClipboardType clipboard_type,
- const base::string16& type,
- base::string16* data) {
- RenderThreadImpl::current()->Send(
- new ClipboardHostMsg_ReadCustomData(clipboard_type, type, data));
-}
-
-ClipboardClient::WriteContext* RendererClipboardClient::CreateWriteContext() {
- return new RendererClipboardWriteContext;
-}
-
-} // namespace content
diff --git a/content/renderer/renderer_clipboard_client.h b/content/renderer/renderer_clipboard_client.h
deleted file mode 100644
index de9e9c1..0000000
--- a/content/renderer/renderer_clipboard_client.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// 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.
-
-#ifndef CONTENT_RENDERER_RENDERER_CLIPBOARD_CLIENT_H_
-#define CONTENT_RENDERER_RENDERER_CLIPBOARD_CLIENT_H_
-
-#include "base/compiler_specific.h"
-#include "content/renderer/clipboard_client.h"
-
-namespace content {
-
-// An implementation of ClipboardClient that gets and sends data over IPC.
-class RendererClipboardClient : public ClipboardClient {
- public:
- RendererClipboardClient();
- ~RendererClipboardClient() override;
-
- ui::Clipboard* GetClipboard() override;
- uint64 GetSequenceNumber(ui::ClipboardType type) override;
- bool IsFormatAvailable(ClipboardFormat format,
- ui::ClipboardType type) override;
- void Clear(ui::ClipboardType type) override;
- void ReadAvailableTypes(ui::ClipboardType type,
- std::vector<base::string16>* types,
- bool* contains_filenames) override;
- void ReadText(ui::ClipboardType type, base::string16* result) override;
- void ReadHTML(ui::ClipboardType type,
- base::string16* markup,
- GURL* url,
- uint32* fragment_start,
- uint32* fragment_end) override;
- void ReadRTF(ui::ClipboardType type, std::string* result) override;
- void ReadImage(ui::ClipboardType type, std::string* data) override;
- void ReadCustomData(ui::ClipboardType clipboard_type,
- const base::string16& type,
- base::string16* data) override;
- WriteContext* CreateWriteContext() override;
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_RENDERER_CLIPBOARD_CLIENT_H_
diff --git a/content/renderer/renderer_clipboard_delegate.cc b/content/renderer/renderer_clipboard_delegate.cc
new file mode 100644
index 0000000..5033220
--- /dev/null
+++ b/content/renderer/renderer_clipboard_delegate.cc
@@ -0,0 +1,165 @@
+// 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.
+
+// This file provides the embedder's side of the Clipboard interface.
+
+#include "content/renderer/renderer_clipboard_delegate.h"
+
+#include "base/memory/shared_memory.h"
+#include "base/numerics/safe_math.h"
+#include "content/common/clipboard_messages.h"
+#include "content/public/renderer/content_renderer_client.h"
+#include "content/renderer/render_thread_impl.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/clipboard/clipboard.h"
+#include "ui/gfx/size.h"
+
+namespace content {
+
+RendererClipboardDelegate::RendererClipboardDelegate() {
+}
+
+uint64 RendererClipboardDelegate::GetSequenceNumber(ui::ClipboardType type) {
+ uint64 sequence_number = 0;
+ RenderThreadImpl::current()->Send(
+ new ClipboardHostMsg_GetSequenceNumber(type, &sequence_number));
+ return sequence_number;
+}
+
+bool RendererClipboardDelegate::IsFormatAvailable(
+ content::ClipboardFormat format,
+ ui::ClipboardType type) {
+ bool result = false;
+ RenderThreadImpl::current()->Send(
+ new ClipboardHostMsg_IsFormatAvailable(format, type, &result));
+ return result;
+}
+
+void RendererClipboardDelegate::Clear(ui::ClipboardType type) {
+ RenderThreadImpl::current()->Send(new ClipboardHostMsg_Clear(type));
+}
+
+void RendererClipboardDelegate::ReadAvailableTypes(
+ ui::ClipboardType type,
+ std::vector<base::string16>* types,
+ bool* contains_filenames) {
+ RenderThreadImpl::current()->Send(
+ new ClipboardHostMsg_ReadAvailableTypes(type, types, contains_filenames));
+}
+
+void RendererClipboardDelegate::ReadText(ui::ClipboardType type,
+ base::string16* result) {
+ RenderThreadImpl::current()->Send(
+ new ClipboardHostMsg_ReadText(type, result));
+}
+
+void RendererClipboardDelegate::ReadHTML(ui::ClipboardType type,
+ base::string16* markup,
+ GURL* url,
+ uint32* fragment_start,
+ uint32* fragment_end) {
+ RenderThreadImpl::current()->Send(new ClipboardHostMsg_ReadHTML(
+ type, markup, url, fragment_start, fragment_end));
+}
+
+void RendererClipboardDelegate::ReadRTF(ui::ClipboardType type,
+ std::string* result) {
+ RenderThreadImpl::current()->Send(new ClipboardHostMsg_ReadRTF(type, result));
+}
+
+void RendererClipboardDelegate::ReadImage(ui::ClipboardType type,
+ std::string* data) {
+ base::SharedMemoryHandle image_handle;
+ uint32 image_size = 0;
+ RenderThreadImpl::current()->Send(
+ new ClipboardHostMsg_ReadImage(type, &image_handle, &image_size));
+ if (base::SharedMemory::IsHandleValid(image_handle)) {
+ base::SharedMemory buffer(image_handle, true);
+ buffer.Map(image_size);
+ data->append(static_cast<char*>(buffer.memory()), image_size);
+ }
+}
+
+void RendererClipboardDelegate::ReadCustomData(ui::ClipboardType clipboard_type,
+ const base::string16& type,
+ base::string16* data) {
+ RenderThreadImpl::current()->Send(
+ new ClipboardHostMsg_ReadCustomData(clipboard_type, type, data));
+}
+
+void RendererClipboardDelegate::WriteText(ui::ClipboardType clipboard_type,
+ const base::string16& text) {
+ RenderThreadImpl::current()->Send(
+ new ClipboardHostMsg_WriteText(clipboard_type, text));
+}
+
+void RendererClipboardDelegate::WriteHTML(ui::ClipboardType clipboard_type,
+ const base::string16& markup,
+ const GURL& url) {
+ RenderThreadImpl::current()->Send(
+ new ClipboardHostMsg_WriteHTML(clipboard_type, markup, url));
+}
+
+void RendererClipboardDelegate::WriteSmartPasteMarker(
+ ui::ClipboardType clipboard_type) {
+ RenderThreadImpl::current()->Send(
+ new ClipboardHostMsg_WriteSmartPasteMarker(clipboard_type));
+}
+
+void RendererClipboardDelegate::WriteCustomData(
+ ui::ClipboardType clipboard_type,
+ const std::map<base::string16, base::string16>& data) {
+ RenderThreadImpl::current()->Send(
+ new ClipboardHostMsg_WriteCustomData(clipboard_type, data));
+}
+
+void RendererClipboardDelegate::WriteBookmark(ui::ClipboardType clipboard_type,
+ const GURL& url,
+ const base::string16& title) {
+ RenderThreadImpl::current()->Send(
+ new ClipboardHostMsg_WriteBookmark(clipboard_type, url, title));
+}
+
+bool RendererClipboardDelegate::WriteImage(ui::ClipboardType clipboard_type,
+ const SkBitmap& bitmap) {
+ // Only 32-bit bitmaps are supported.
+ DCHECK_EQ(bitmap.colorType(), kN32_SkColorType);
+
+ const gfx::Size size(bitmap.width(), bitmap.height());
+ scoped_ptr<base::SharedMemory> shared_buf;
+ {
+ SkAutoLockPixels locked(bitmap);
+ void* pixels = bitmap.getPixels();
+ // TODO(piman): this should not be NULL, but it is. crbug.com/369621
+ if (!pixels)
+ return false;
+
+ base::CheckedNumeric<uint32> checked_buf_size = 4;
+ checked_buf_size *= size.width();
+ checked_buf_size *= size.height();
+ if (!checked_buf_size.IsValid())
+ return false;
+
+ // Allocate a shared memory buffer to hold the bitmap bits.
+ uint32 buf_size = checked_buf_size.ValueOrDie();
+ shared_buf.reset(ChildThread::current()->AllocateSharedMemory(buf_size));
+ if (!shared_buf)
+ return false;
+ // Copy the bits into shared memory
+ DCHECK(shared_buf->memory());
+ memcpy(shared_buf->memory(), pixels, buf_size);
+ shared_buf->Unmap();
+ }
+
+ RenderThreadImpl::current()->Send(new ClipboardHostMsg_WriteImage(
+ clipboard_type, size, shared_buf->handle()));
+ return true;
+}
+
+void RendererClipboardDelegate::CommitWrite(ui::ClipboardType clipboard_type) {
+ RenderThreadImpl::current()->Send(
+ new ClipboardHostMsg_CommitWrite(clipboard_type));
+}
+
+} // namespace content
diff --git a/content/renderer/renderer_clipboard_delegate.h b/content/renderer/renderer_clipboard_delegate.h
new file mode 100644
index 0000000..ef8e034
--- /dev/null
+++ b/content/renderer/renderer_clipboard_delegate.h
@@ -0,0 +1,66 @@
+// 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.
+
+#ifndef CONTENT_RENDERER_RENDERER_CLIPBOARD_DELEGATE_H_
+#define CONTENT_RENDERER_RENDERER_CLIPBOARD_DELEGATE_H_
+
+#include <stdint.h>
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "base/strings/string16.h"
+#include "content/common/clipboard_format.h"
+#include "ui/base/clipboard/clipboard_types.h"
+
+class GURL;
+class SkBitmap;
+
+namespace content {
+
+// Renderer interface to read/write from the clipboard over IPC.
+class RendererClipboardDelegate {
+ public:
+ RendererClipboardDelegate();
+
+ uint64 GetSequenceNumber(ui::ClipboardType type);
+ bool IsFormatAvailable(ClipboardFormat format, ui::ClipboardType type);
+ void Clear(ui::ClipboardType type);
+ void ReadAvailableTypes(ui::ClipboardType type,
+ std::vector<base::string16>* types,
+ bool* contains_filenames);
+ void ReadText(ui::ClipboardType type, base::string16* result);
+ void ReadHTML(ui::ClipboardType type,
+ base::string16* markup,
+ GURL* url,
+ uint32* fragment_start,
+ uint32* fragment_end);
+ void ReadRTF(ui::ClipboardType type, std::string* result);
+ void ReadImage(ui::ClipboardType type, std::string* data);
+ void ReadCustomData(ui::ClipboardType clipboard_type,
+ const base::string16& type,
+ base::string16* data);
+
+ void WriteText(ui::ClipboardType type, const base::string16& text);
+ void WriteHTML(ui::ClipboardType type,
+ const base::string16& markup,
+ const GURL& url);
+ void WriteSmartPasteMarker(ui::ClipboardType type);
+ void WriteCustomData(ui::ClipboardType type,
+ const std::map<base::string16, base::string16>& data);
+ void WriteBookmark(ui::ClipboardType type,
+ const GURL& url,
+ const base::string16& title);
+ bool WriteImage(ui::ClipboardType type, const SkBitmap& bitmap);
+ void CommitWrite(ui::ClipboardType type);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(RendererClipboardDelegate);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_RENDERER_CLIPBOARD_DELEGATE_H_
diff --git a/content/renderer/scoped_clipboard_writer_glue.cc b/content/renderer/scoped_clipboard_writer_glue.cc
deleted file mode 100644
index 7147134..0000000
--- a/content/renderer/scoped_clipboard_writer_glue.cc
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) 2013 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/renderer/scoped_clipboard_writer_glue.h"
-#include "base/logging.h"
-
-namespace content {
-
-ScopedClipboardWriterGlue::ScopedClipboardWriterGlue(ClipboardClient* client)
- : ui::ScopedClipboardWriter(ui::CLIPBOARD_TYPE_COPY_PASTE),
- context_(client->CreateWriteContext()) {
- DCHECK(context_);
-}
-
-ScopedClipboardWriterGlue::~ScopedClipboardWriterGlue() {
- if (!objects_.empty() && context_) {
- context_->Flush(objects_);
- // TODO(dcheng): Temporary hack while the clipboard IPCs are cleaned up.
- // This prevents the base class destructor from also trying to (probably
- // unsuccessfully) flush things to the clipboard.
- objects_.clear();
- }
-}
-
-void ScopedClipboardWriterGlue::WriteBitmapFromPixels(const void* pixels,
- const gfx::Size& size) {
- if (context_) {
- context_->WriteBitmapFromPixels(&objects_, pixels, size);
- } else {
- NOTREACHED();
- }
-}
-
-} // namespace content
-
diff --git a/content/renderer/scoped_clipboard_writer_glue.h b/content/renderer/scoped_clipboard_writer_glue.h
deleted file mode 100644
index d64ae63..0000000
--- a/content/renderer/scoped_clipboard_writer_glue.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2013 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.
-
-#ifndef CONTENT_RENDERER_SCOPED_CLIPBOARD_WRITER_GLUE_H_
-#define CONTENT_RENDERER_SCOPED_CLIPBOARD_WRITER_GLUE_H_
-
-#include "ui/base/clipboard/scoped_clipboard_writer.h"
-#include "base/memory/scoped_ptr.h"
-#include "content/renderer/clipboard_client.h"
-
-namespace content {
-
-class ScopedClipboardWriterGlue
- : public ui::ScopedClipboardWriter {
- public:
- explicit ScopedClipboardWriterGlue(ClipboardClient* client);
-
- virtual ~ScopedClipboardWriterGlue();
-
- void WriteBitmapFromPixels(const void* pixels, const gfx::Size& size);
-
- private:
- scoped_ptr<ClipboardClient::WriteContext> context_;
- DISALLOW_COPY_AND_ASSIGN(ScopedClipboardWriterGlue);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_SCOPED_CLIPBOARD_WRITER_GLUE_H_
diff --git a/content/renderer/webclipboard_impl.cc b/content/renderer/webclipboard_impl.cc
index e248c51..19f2362 100644
--- a/content/renderer/webclipboard_impl.cc
+++ b/content/renderer/webclipboard_impl.cc
@@ -5,14 +5,13 @@
#include "content/renderer/webclipboard_impl.h"
#include "base/logging.h"
-#include "base/pickle.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "content/common/clipboard_format.h"
#include "content/public/common/drop_data.h"
#include "content/renderer/clipboard_utils.h"
#include "content/renderer/drop_data_builder.h"
-#include "content/renderer/scoped_clipboard_writer_glue.h"
+#include "content/renderer/renderer_clipboard_delegate.h"
#include "third_party/WebKit/public/platform/WebData.h"
#include "third_party/WebKit/public/platform/WebDragData.h"
#include "third_party/WebKit/public/platform/WebImage.h"
@@ -20,9 +19,6 @@
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/platform/WebVector.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "ui/base/clipboard/clipboard.h"
-#include "ui/base/clipboard/custom_data_helper.h"
#include "url/gurl.h"
using blink::WebClipboard;
@@ -35,8 +31,9 @@ using blink::WebVector;
namespace content {
-WebClipboardImpl::WebClipboardImpl(ClipboardClient* client)
- : client_(client) {
+WebClipboardImpl::WebClipboardImpl(RendererClipboardDelegate* delegate)
+ : delegate_(delegate) {
+ DCHECK(delegate);
}
WebClipboardImpl::~WebClipboardImpl() {
@@ -47,7 +44,7 @@ uint64 WebClipboardImpl::sequenceNumber(Buffer buffer) {
if (!ConvertBufferType(buffer, &clipboard_type))
return 0;
- return client_->GetSequenceNumber(clipboard_type);
+ return delegate_->GetSequenceNumber(clipboard_type);
}
bool WebClipboardImpl::isFormatAvailable(Format format, Buffer buffer) {
@@ -58,16 +55,17 @@ bool WebClipboardImpl::isFormatAvailable(Format format, Buffer buffer) {
switch (format) {
case FormatPlainText:
- return client_->IsFormatAvailable(CLIPBOARD_FORMAT_PLAINTEXT,
- clipboard_type);
+ return delegate_->IsFormatAvailable(CLIPBOARD_FORMAT_PLAINTEXT,
+ clipboard_type);
case FormatHTML:
- return client_->IsFormatAvailable(CLIPBOARD_FORMAT_HTML, clipboard_type);
+ return delegate_->IsFormatAvailable(CLIPBOARD_FORMAT_HTML,
+ clipboard_type);
case FormatSmartPaste:
- return client_->IsFormatAvailable(CLIPBOARD_FORMAT_SMART_PASTE,
- clipboard_type);
+ return delegate_->IsFormatAvailable(CLIPBOARD_FORMAT_SMART_PASTE,
+ clipboard_type);
case FormatBookmark:
- return client_->IsFormatAvailable(CLIPBOARD_FORMAT_BOOKMARK,
- clipboard_type);
+ return delegate_->IsFormatAvailable(CLIPBOARD_FORMAT_BOOKMARK,
+ clipboard_type);
default:
NOTREACHED();
}
@@ -80,7 +78,7 @@ WebVector<WebString> WebClipboardImpl::readAvailableTypes(
ui::ClipboardType clipboard_type;
std::vector<base::string16> types;
if (ConvertBufferType(buffer, &clipboard_type)) {
- client_->ReadAvailableTypes(clipboard_type, &types, contains_filenames);
+ delegate_->ReadAvailableTypes(clipboard_type, &types, contains_filenames);
}
return types;
}
@@ -91,7 +89,7 @@ WebString WebClipboardImpl::readPlainText(Buffer buffer) {
return WebString();
base::string16 text;
- client_->ReadText(clipboard_type, &text);
+ delegate_->ReadText(clipboard_type, &text);
return text;
}
@@ -104,9 +102,9 @@ WebString WebClipboardImpl::readHTML(Buffer buffer, WebURL* source_url,
base::string16 html_stdstr;
GURL gurl;
- client_->ReadHTML(clipboard_type, &html_stdstr, &gurl,
- static_cast<uint32*>(fragment_start),
- static_cast<uint32*>(fragment_end));
+ delegate_->ReadHTML(clipboard_type, &html_stdstr, &gurl,
+ static_cast<uint32*>(fragment_start),
+ static_cast<uint32*>(fragment_end));
*source_url = gurl;
return html_stdstr;
}
@@ -117,7 +115,7 @@ WebData WebClipboardImpl::readImage(Buffer buffer) {
return WebData();
std::string png_data;
- client_->ReadImage(clipboard_type, &png_data);
+ delegate_->ReadImage(clipboard_type, &png_data);
return WebData(png_data);
}
@@ -128,46 +126,36 @@ WebString WebClipboardImpl::readCustomData(Buffer buffer,
return WebString();
base::string16 data;
- client_->ReadCustomData(clipboard_type, type, &data);
+ delegate_->ReadCustomData(clipboard_type, type, &data);
return data;
}
void WebClipboardImpl::writePlainText(const WebString& plain_text) {
- ScopedClipboardWriterGlue scw(client_);
- scw.WriteText(plain_text);
+ delegate_->WriteText(ui::CLIPBOARD_TYPE_COPY_PASTE, plain_text);
+ delegate_->CommitWrite(ui::CLIPBOARD_TYPE_COPY_PASTE);
}
void WebClipboardImpl::writeHTML(
const WebString& html_text, const WebURL& source_url,
const WebString& plain_text, bool write_smart_paste) {
- ScopedClipboardWriterGlue scw(client_);
- scw.WriteHTML(html_text, source_url.spec());
- scw.WriteText(plain_text);
+ delegate_->WriteHTML(ui::CLIPBOARD_TYPE_COPY_PASTE, html_text, source_url);
+ delegate_->WriteText(ui::CLIPBOARD_TYPE_COPY_PASTE, plain_text);
if (write_smart_paste)
- scw.WriteWebSmartPaste();
+ delegate_->WriteSmartPasteMarker(ui::CLIPBOARD_TYPE_COPY_PASTE);
+ delegate_->CommitWrite(ui::CLIPBOARD_TYPE_COPY_PASTE);
}
void WebClipboardImpl::writeImage(const WebImage& image,
const WebURL& url,
const WebString& title) {
- ScopedClipboardWriterGlue scw(client_);
-
- if (!image.isNull()) {
- const SkBitmap& bitmap = image.getSkBitmap();
- // WriteBitmapFromPixels expects 32-bit data.
- DCHECK_EQ(bitmap.colorType(), kN32_SkColorType);
-
- SkAutoLockPixels locked(bitmap);
- void *pixels = bitmap.getPixels();
- // TODO(piman): this should not be NULL, but it is. crbug.com/369621
- if (!pixels)
- return;
- scw.WriteBitmapFromPixels(pixels, image.size());
- }
+ DCHECK(!image.isNull());
+ const SkBitmap& bitmap = image.getSkBitmap();
+ if (!delegate_->WriteImage(ui::CLIPBOARD_TYPE_COPY_PASTE, bitmap))
+ return;
if (!url.isEmpty()) {
- scw.WriteBookmark(title, url.spec());
+ delegate_->WriteBookmark(ui::CLIPBOARD_TYPE_COPY_PASTE, url, title);
#if !defined(OS_MACOSX)
// When writing the image, we also write the image markup so that pasting
// into rich text editors, such as Gmail, reveals the image. We also don't
@@ -176,31 +164,30 @@ void WebClipboardImpl::writeImage(const WebImage& image,
// We also don't want to write HTML on a Mac, since Mail.app prefers to use
// the image markup over attaching the actual image. See
// http://crbug.com/33016 for details.
- scw.WriteHTML(base::UTF8ToUTF16(URLToImageMarkup(url, title)),
- std::string());
+ delegate_->WriteHTML(ui::CLIPBOARD_TYPE_COPY_PASTE,
+ base::UTF8ToUTF16(URLToImageMarkup(url, title)),
+ GURL());
#endif
}
+ delegate_->CommitWrite(ui::CLIPBOARD_TYPE_COPY_PASTE);
}
void WebClipboardImpl::writeDataObject(const WebDragData& data) {
- ScopedClipboardWriterGlue scw(client_);
-
const DropData& data_object = DropDataBuilder::Build(data);
// TODO(dcheng): Properly support text/uri-list here.
+ // Avoid calling the WriteFoo functions if there is no data associated with a
+ // type. This prevents stomping on clipboard contents that might have been
+ // written by extension functions such as chrome.bookmarkManagerPrivate.copy.
if (!data_object.text.is_null())
- scw.WriteText(data_object.text.string());
+ delegate_->WriteText(ui::CLIPBOARD_TYPE_COPY_PASTE,
+ data_object.text.string());
if (!data_object.html.is_null())
- scw.WriteHTML(data_object.html.string(), std::string());
- // If there is no custom data, avoid calling WritePickledData. This ensures
- // that ScopedClipboardWriterGlue's dtor remains a no-op if the page didn't
- // modify the DataTransfer object, which is important to avoid stomping on
- // any clipboard contents written by extension functions such as
- // chrome.bookmarkManagerPrivate.copy.
- if (!data_object.custom_data.empty()) {
- Pickle pickle;
- ui::WriteCustomDataToPickle(data_object.custom_data, &pickle);
- scw.WritePickledData(pickle, ui::Clipboard::GetWebCustomDataFormatType());
- }
+ delegate_->WriteHTML(ui::CLIPBOARD_TYPE_COPY_PASTE,
+ data_object.html.string(), GURL());
+ if (!data_object.custom_data.empty())
+ delegate_->WriteCustomData(ui::CLIPBOARD_TYPE_COPY_PASTE,
+ data_object.custom_data);
+ delegate_->CommitWrite(ui::CLIPBOARD_TYPE_COPY_PASTE);
}
bool WebClipboardImpl::ConvertBufferType(Buffer buffer,
diff --git a/content/renderer/webclipboard_impl.h b/content/renderer/webclipboard_impl.h
index 477f53b..9288546 100644
--- a/content/renderer/webclipboard_impl.h
+++ b/content/renderer/webclipboard_impl.h
@@ -6,18 +6,17 @@
#define CONTENT_RENDERER_WEBCLIPBOARD_IMPL_H_
#include "base/compiler_specific.h"
-
#include "third_party/WebKit/public/platform/WebClipboard.h"
#include "ui/base/clipboard/clipboard.h"
#include <string>
namespace content {
-class ClipboardClient;
+class RendererClipboardDelegate;
class WebClipboardImpl : public blink::WebClipboard {
public:
- explicit WebClipboardImpl(ClipboardClient* client);
+ explicit WebClipboardImpl(RendererClipboardDelegate* delegate);
virtual ~WebClipboardImpl();
@@ -49,7 +48,7 @@ class WebClipboardImpl : public blink::WebClipboard {
private:
bool ConvertBufferType(Buffer, ui::ClipboardType*);
- ClipboardClient* client_;
+ RendererClipboardDelegate* const delegate_;
};
} // namespace content