summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/chrome_common.gypi1
-rw-r--r--chrome/common/net/BUILD.gn1
-rw-r--r--components/bookmarks/browser/BUILD.gn1
-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
-rw-r--r--ui/base/clipboard/clipboard.cc111
-rw-r--r--ui/base/clipboard/clipboard.h99
-rw-r--r--ui/base/clipboard/clipboard_test_template.h242
-rw-r--r--ui/base/clipboard/clipboard_util_win.cc1
-rw-r--r--ui/base/clipboard/scoped_clipboard_writer.cc17
-rw-r--r--ui/base/clipboard/scoped_clipboard_writer.h8
-rw-r--r--ui/base/test/test_clipboard.cc6
-rw-r--r--ui/base/test/test_clipboard.h5
-rw-r--r--ui/base/test/test_clipboard_unittest.cc5
-rw-r--r--ui/base/ui_base.gyp1
30 files changed, 737 insertions, 895 deletions
diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi
index 285a9d3..19f8609 100644
--- a/chrome/chrome_common.gypi
+++ b/chrome/chrome_common.gypi
@@ -607,6 +607,7 @@
'<(DEPTH)/net/net.gyp:net',
'<(DEPTH)/third_party/icu/icu.gyp:icui18n',
'<(DEPTH)/third_party/icu/icu.gyp:icuuc',
+ '<(DEPTH)/ui/base/ui_base.gyp:ui_base',
],
'conditions': [
['OS != "ios"', {
diff --git a/chrome/common/net/BUILD.gn b/chrome/common/net/BUILD.gn
index 143512d..0794d86 100644
--- a/chrome/common/net/BUILD.gn
+++ b/chrome/common/net/BUILD.gn
@@ -26,6 +26,7 @@ static_library("net") {
"//net",
"//net:net_resources",
"//third_party/icu",
+ "//ui/base/",
]
if (is_ios) {
diff --git a/components/bookmarks/browser/BUILD.gn b/components/bookmarks/browser/BUILD.gn
index 61c2974..18f84bf 100644
--- a/components/bookmarks/browser/BUILD.gn
+++ b/components/bookmarks/browser/BUILD.gn
@@ -73,5 +73,6 @@ source_set("unit_tests") {
deps = [
":browser",
"//testing/gtest",
+ "//ui/base",
]
}
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
diff --git a/ui/base/clipboard/clipboard.cc b/ui/base/clipboard/clipboard.cc
index 0bd542d..aedc54b 100644
--- a/ui/base/clipboard/clipboard.cc
+++ b/ui/base/clipboard/clipboard.cc
@@ -14,27 +14,6 @@
namespace ui {
-namespace {
-
-// Valides a shared bitmap on the clipboard.
-// Returns true if the clipboard data makes sense and it's safe to access the
-// bitmap.
-bool ValidateAndMapSharedBitmap(size_t bitmap_bytes,
- base::SharedMemory* bitmap_data) {
- using base::SharedMemory;
-
- if (!bitmap_data || !SharedMemory::IsHandleValid(bitmap_data->handle()))
- return false;
-
- if (!bitmap_data->Map(bitmap_bytes)) {
- PLOG(ERROR) << "Failed to map bitmap memory";
- return false;
- }
- return true;
-}
-
-} // namespace
-
base::LazyInstance<Clipboard::AllowedThreadsVector>
Clipboard::allowed_threads_ = LAZY_INSTANCE_INITIALIZER;
base::LazyInstance<Clipboard::ClipboardMap> Clipboard::clipboard_map_ =
@@ -95,13 +74,12 @@ void Clipboard::DestroyClipboardForCurrentThread() {
}
void Clipboard::DispatchObject(ObjectType type, const ObjectMapParams& params) {
- // All types apart from CBF_WEBKIT need at least 1 non-empty param.
- if (type != CBF_WEBKIT && (params.empty() || params[0].empty()))
- return;
- // Some other types need a non-empty 2nd param.
- if ((type == CBF_BOOKMARK || type == CBF_SMBITMAP || type == CBF_DATA) &&
- (params.size() != 2 || params[1].empty()))
- return;
+ // Ignore writes with empty parameters.
+ for (const auto& param : params) {
+ if (param.empty())
+ return;
+ }
+
switch (type) {
case CBF_TEXT:
WriteText(&(params[0].front()), params[0].size());
@@ -132,41 +110,12 @@ void Clipboard::DispatchObject(ObjectType type, const ObjectMapParams& params) {
break;
case CBF_SMBITMAP: {
- using base::SharedMemory;
- using base::SharedMemoryHandle;
-
- if (params[0].size() != sizeof(SharedMemory*) ||
- params[1].size() != sizeof(gfx::Size)) {
- return;
- }
-
- SkBitmap bitmap;
- const gfx::Size* unvalidated_size =
- reinterpret_cast<const gfx::Size*>(&params[1].front());
- // Let Skia do some sanity checking for us (no negative widths/heights, no
- // overflows while calculating bytes per row, etc).
- if (!bitmap.setInfo(SkImageInfo::MakeN32Premul(
- unvalidated_size->width(), unvalidated_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;
-
- // It's OK to cast away constness here since we map the handle as
- // read-only.
- const char* raw_bitmap_data_const =
- reinterpret_cast<const char*>(&params[0].front());
- char* raw_bitmap_data = const_cast<char*>(raw_bitmap_data_const);
- scoped_ptr<SharedMemory> bitmap_data(
- *reinterpret_cast<SharedMemory**>(raw_bitmap_data));
-
- if (!ValidateAndMapSharedBitmap(bitmap.getSize(), bitmap_data.get()))
- return;
- bitmap.setPixels(bitmap_data->memory());
-
- WriteBitmap(bitmap);
+ // Usually, the params are just UTF-8 strings. However, for images,
+ // ScopedClipboardWriter actually sizes the buffer to sizeof(SkBitmap*),
+ // aliases the contents of the vector to a SkBitmap**, and writes the
+ // pointer to the actual SkBitmap in the clipboard object param.
+ const char* packed_pointer_buffer = &params[0].front();
+ WriteBitmap(**reinterpret_cast<SkBitmap* const*>(packed_pointer_buffer));
break;
}
@@ -183,40 +132,4 @@ void Clipboard::DispatchObject(ObjectType type, const ObjectMapParams& params) {
}
}
-// static
-bool Clipboard::ReplaceSharedMemHandle(ObjectMap* objects,
- base::SharedMemoryHandle bitmap_handle,
- base::ProcessHandle process) {
- using base::SharedMemory;
- bool has_shared_bitmap = false;
-
- for (ObjectMap::iterator iter = objects->begin(); iter != objects->end();
- ++iter) {
- if (iter->first == CBF_SMBITMAP) {
- // The code currently only accepts sending a single bitmap over this way.
- // Fail if we ever encounter more than one shmem bitmap structure to fill.
- if (has_shared_bitmap)
- return false;
-
-#if defined(OS_WIN)
- SharedMemory* bitmap = new SharedMemory(bitmap_handle, true, process);
-#else
- SharedMemory* bitmap = new SharedMemory(bitmap_handle, true);
-#endif
-
- // There must always be two parameters associated with each shmem bitmap.
- if (iter->second.size() != 2)
- return false;
-
- // We store the shared memory object pointer so it can be retrieved by the
- // UI thread (see DispatchObject()).
- iter->second[0].clear();
- for (size_t i = 0; i < sizeof(SharedMemory*); ++i)
- iter->second[0].push_back(reinterpret_cast<char*>(&bitmap)[i]);
- has_shared_bitmap = true;
- }
- }
- return true;
-}
-
} // namespace ui
diff --git a/ui/base/clipboard/clipboard.h b/ui/base/clipboard/clipboard.h
index ab3d34b..6c23a6d 100644
--- a/ui/base/clipboard/clipboard.h
+++ b/ui/base/clipboard/clipboard.h
@@ -32,11 +32,6 @@ class MessageWindow;
} // namespace win
} // namespace base
-// TODO(dcheng): Temporary until the IPC layer doesn't use WriteObjects().
-namespace content {
-class ClipboardMessageFilter;
-}
-
namespace gfx {
class Size;
}
@@ -118,48 +113,6 @@ class UI_BASE_EXPORT Clipboard : NON_EXPORTED_BASE(public base::ThreadChecker) {
// Copyable and assignable, since this is essentially an opaque value type.
};
- // TODO(dcheng): Make this private once the IPC layer no longer needs to
- // serialize this information.
- // ObjectType designates the type of data to be stored in the clipboard. This
- // designation is shared across all OSes. The system-specific designation
- // is defined by FormatType. A single ObjectType might be represented by
- // several system-specific FormatTypes. For example, on Linux the CBF_TEXT
- // ObjectType maps to "text/plain", "STRING", and several other formats. On
- // windows it maps to CF_UNICODETEXT.
- enum ObjectType {
- CBF_TEXT,
- CBF_HTML,
- CBF_RTF,
- CBF_BOOKMARK,
- CBF_WEBKIT,
- CBF_SMBITMAP, // Bitmap from shared memory.
- CBF_DATA, // Arbitrary block of bytes.
- };
-
- // ObjectMap is a map from ObjectType to associated data.
- // The data is organized differently for each ObjectType. The following
- // table summarizes what kind of data is stored for each key.
- // * indicates an optional argument.
- //
- // Key Arguments Type
- // -------------------------------------
- // CBF_TEXT text char array
- // CBF_HTML html char array
- // url* char array
- // CBF_RTF data byte array
- // CBF_BOOKMARK html char array
- // url char array
- // CBF_WEBKIT none empty vector
- // CBF_SMBITMAP shared_mem A pointer to an unmapped base::SharedMemory
- // object containing the bitmap data. The bitmap
- // data should be premultiplied.
- // size gfx::Size struct
- // CBF_DATA format char array
- // data byte array
- typedef std::vector<char> ObjectMapParam;
- typedef std::vector<ObjectMapParam> ObjectMapParams;
- typedef std::map<int /* ObjectType */, ObjectMapParams> ObjectMap;
-
static bool IsSupportedClipboardType(int32 type) {
switch (type) {
case CLIPBOARD_TYPE_COPY_PASTE:
@@ -267,15 +220,6 @@ class UI_BASE_EXPORT Clipboard : NON_EXPORTED_BASE(public base::ThreadChecker) {
static const FormatType& GetWebCustomDataFormatType();
static const FormatType& GetPepperCustomDataFormatType();
- // Embeds a pointer to a SharedMemory object pointed to by |bitmap_handle|
- // belonging to |process| into a shared bitmap [CBF_SMBITMAP] slot in
- // |objects|. The pointer is deleted by DispatchObjects().
- //
- // On non-Windows platforms, |process| is ignored.
- static bool ReplaceSharedMemHandle(ObjectMap* objects,
- base::SharedMemoryHandle bitmap_handle,
- base::ProcessHandle process)
- WARN_UNUSED_RESULT;
#if defined(OS_WIN)
// Firefox text/html
static const FormatType& GetTextHtmlFormatType();
@@ -291,6 +235,45 @@ class UI_BASE_EXPORT Clipboard : NON_EXPORTED_BASE(public base::ThreadChecker) {
Clipboard() {}
virtual ~Clipboard() {}
+ // ObjectType designates the type of data to be stored in the clipboard. This
+ // designation is shared across all OSes. The system-specific designation
+ // is defined by FormatType. A single ObjectType might be represented by
+ // several system-specific FormatTypes. For example, on Linux the CBF_TEXT
+ // ObjectType maps to "text/plain", "STRING", and several other formats. On
+ // windows it maps to CF_UNICODETEXT.
+ enum ObjectType {
+ CBF_TEXT,
+ CBF_HTML,
+ CBF_RTF,
+ CBF_BOOKMARK,
+ CBF_WEBKIT,
+ CBF_SMBITMAP, // Bitmap from shared memory.
+ CBF_DATA, // Arbitrary block of bytes.
+ };
+
+ // ObjectMap is a map from ObjectType to associated data.
+ // The data is organized differently for each ObjectType. The following
+ // table summarizes what kind of data is stored for each key.
+ // * indicates an optional argument.
+ //
+ // Key Arguments Type
+ // -------------------------------------
+ // CBF_TEXT text char array
+ // CBF_HTML html char array
+ // url* char array
+ // CBF_RTF data byte array
+ // CBF_BOOKMARK html char array
+ // url char array
+ // CBF_WEBKIT none empty vector
+ // CBF_SMBITMAP bitmap A pointer to a SkBitmap. The caller must ensure
+ // the SkBitmap remains live for the duration of
+ // the WriteObjects call.
+ // CBF_DATA format char array
+ // data byte array
+ typedef std::vector<char> ObjectMapParam;
+ typedef std::vector<ObjectMapParam> ObjectMapParams;
+ typedef std::map<int /* ObjectType */, ObjectMapParams> ObjectMap;
+
// Write a bunch of objects to the system clipboard. Copies are made of the
// contents of |objects|.
virtual void WriteObjects(ClipboardType type, const ObjectMap& objects) = 0;
@@ -320,11 +303,7 @@ class UI_BASE_EXPORT Clipboard : NON_EXPORTED_BASE(public base::ThreadChecker) {
size_t data_len) = 0;
private:
- template <typename T>
- friend class ClipboardTest;
// For access to WriteObjects().
- // TODO(dcheng): Remove the temporary exception for content.
- friend class content::ClipboardMessageFilter;
friend class ScopedClipboardWriter;
friend class TestClipboard;
diff --git a/ui/base/clipboard/clipboard_test_template.h b/ui/base/clipboard/clipboard_test_template.h
index 2a6c2a7..b5df843 100644
--- a/ui/base/clipboard/clipboard_test_template.h
+++ b/ui/base/clipboard/clipboard_test_template.h
@@ -61,18 +61,9 @@ class ClipboardTest : public PlatformTest {
~ClipboardTest() override { ClipboardTraits::Destroy(clipboard_); }
- static void WriteObjectsToClipboard(ui::Clipboard* clipboard,
- const Clipboard::ObjectMap& objects) {
- clipboard->WriteObjects(ui::CLIPBOARD_TYPE_COPY_PASTE, objects);
- }
-
protected:
Clipboard& clipboard() { return *clipboard_; }
- void WriteObjectsToClipboard(const Clipboard::ObjectMap& objects) {
- WriteObjectsToClipboard(&clipboard(), objects);
- }
-
private:
base::MessageLoopForUI message_loop_;
#if defined(USE_AURA)
@@ -349,54 +340,18 @@ TYPED_TEST(ClipboardTest, URLTest) {
#endif
}
-// TODO(dcheng): The tests for copying to the clipboard also test IPC
-// interaction... consider moving them to a different layer so we can
-// consolidate the validation logic.
-// Note that |bitmap_data| is not premultiplied!
static void TestBitmapWrite(Clipboard* clipboard,
- const uint32* bitmap_data,
- size_t bitmap_data_size,
- const gfx::Size& size) {
- // Create shared memory region.
- base::SharedMemory shared_buf;
- ASSERT_TRUE(shared_buf.CreateAndMapAnonymous(bitmap_data_size));
- memcpy(shared_buf.memory(), bitmap_data, bitmap_data_size);
- // CBF_SMBITMAP expects premultiplied bitmap data so do that now.
- uint32* pixel_buffer = static_cast<uint32*>(shared_buf.memory());
- for (int j = 0; j < size.height(); ++j) {
- for (int i = 0; i < size.width(); ++i) {
- uint32& pixel = pixel_buffer[i + j * size.width()];
- pixel = SkPreMultiplyColor(pixel);
- }
+ const gfx::Size& size,
+ const uint32* bitmap_data) {
+ {
+ ScopedClipboardWriter scw(CLIPBOARD_TYPE_COPY_PASTE);
+ SkBitmap bitmap;
+ ASSERT_TRUE(bitmap.setInfo(
+ SkImageInfo::MakeN32Premul(size.width(), size.height())));
+ bitmap.setPixels(
+ const_cast<void*>(reinterpret_cast<const void*>(bitmap_data)));
+ scw.WriteImage(bitmap);
}
- base::SharedMemoryHandle handle_to_share;
- base::ProcessHandle current_process = base::kNullProcessHandle;
-#if defined(OS_WIN)
- current_process = GetCurrentProcess();
-#endif
- shared_buf.ShareToProcess(current_process, &handle_to_share);
- ASSERT_TRUE(shared_buf.Unmap());
-
- // Setup data for clipboard().
- Clipboard::ObjectMapParam placeholder_param;
- Clipboard::ObjectMapParam size_param;
- const char* size_data = reinterpret_cast<const char*>(&size);
- for (size_t i = 0; i < sizeof(size); ++i)
- size_param.push_back(size_data[i]);
-
- Clipboard::ObjectMapParams params;
- params.push_back(placeholder_param);
- params.push_back(size_param);
-
- Clipboard::ObjectMap objects;
- objects[Clipboard::CBF_SMBITMAP] = params;
- ASSERT_TRUE(Clipboard::ReplaceSharedMemHandle(&objects, handle_to_share,
- current_process));
-
- // This is pretty ugly, but the template type parameter is irrelevant... and
- // this test will be going away anyway.
- ClipboardTest<NullClipboardTraits>::WriteObjectsToClipboard(clipboard,
- objects);
EXPECT_TRUE(clipboard->IsFormatAvailable(Clipboard::GetBitmapFormatType(),
CLIPBOARD_TYPE_COPY_PASTE));
@@ -407,145 +362,38 @@ static void TestBitmapWrite(Clipboard* clipboard,
const uint32* row_address = image.getAddr32(0, j);
for (int i = 0; i < image.width(); ++i) {
int offset = i + j * image.width();
- uint32 pixel = SkPreMultiplyColor(bitmap_data[offset]);
- EXPECT_EQ(pixel, row_address[i]) << "i = " << i << ", j = " << j;
+ EXPECT_EQ(bitmap_data[offset], row_address[i]) << "i = " << i
+ << ", j = " << j;
}
}
}
TYPED_TEST(ClipboardTest, SharedBitmapTest) {
const uint32 fake_bitmap_1[] = {
- 0x46155189, 0xF6A55C8D, 0x79845674, 0xFA57BD89,
- 0x78FD46AE, 0x87C64F5A, 0x36EDC5AF, 0x4378F568,
- 0x91E9F63A, 0xC31EA14F, 0x69AB32DF, 0x643A3FD1,
+ 0x46061626, 0xf69f5988, 0x793f2937, 0xfa55b986,
+ 0x78772152, 0x87692a30, 0x36322a25, 0x4320401b,
+ 0x91848c21, 0xc3177b3c, 0x6946155c, 0x64171952,
};
{
SCOPED_TRACE("first bitmap");
- TestBitmapWrite(&this->clipboard(), fake_bitmap_1, sizeof(fake_bitmap_1),
- gfx::Size(4, 3));
+ TestBitmapWrite(&this->clipboard(), gfx::Size(4, 3), fake_bitmap_1);
}
const uint32 fake_bitmap_2[] = {
- 0x46155189, 0xF6A55C8D,
- 0x79845674, 0xFA57BD89,
- 0x78FD46AE, 0x87C64F5A,
- 0x36EDC5AF, 0x4378F568,
- 0x91E9F63A, 0xC31EA14F,
- 0x69AB32DF, 0x643A3FD1,
- 0xA6DF041D, 0x83046278,
+ 0x46061626, 0xf69f5988,
+ 0x793f2937, 0xfa55b986,
+ 0x78772152, 0x87692a30,
+ 0x36322a25, 0x4320401b,
+ 0x91848c21, 0xc3177b3c,
+ 0x6946155c, 0x64171952,
+ 0xa6910313, 0x8302323e,
};
{
SCOPED_TRACE("second bitmap");
- TestBitmapWrite(&this->clipboard(), fake_bitmap_2, sizeof(fake_bitmap_2),
- gfx::Size(2, 7));
+ TestBitmapWrite(&this->clipboard(), gfx::Size(2, 7), fake_bitmap_2);
}
}
-namespace {
-// A size class that just happens to have the same layout as gfx::Size!
-struct UnsafeSize {
- int width;
- int height;
-};
-COMPILE_ASSERT(sizeof(UnsafeSize) == sizeof(gfx::Size),
- UnsafeSize_must_be_same_size_as_gfx_Size);
-} // namespace
-
-TYPED_TEST(ClipboardTest, SharedBitmapWithTwoNegativeSizes) {
- Clipboard::ObjectMapParam placeholder_param;
- void* crash_me = reinterpret_cast<void*>(57);
- placeholder_param.resize(sizeof(crash_me));
- memcpy(&placeholder_param.front(), &crash_me, sizeof(crash_me));
-
- Clipboard::ObjectMapParam size_param;
- UnsafeSize size = {-100, -100};
- size_param.resize(sizeof(size));
- memcpy(&size_param.front(), &size, sizeof(size));
-
- Clipboard::ObjectMapParams params;
- params.push_back(placeholder_param);
- params.push_back(size_param);
-
- Clipboard::ObjectMap objects;
- objects[Clipboard::CBF_SMBITMAP] = params;
-
- this->WriteObjectsToClipboard(objects);
- EXPECT_FALSE(this->clipboard().IsFormatAvailable(
- Clipboard::GetBitmapFormatType(), CLIPBOARD_TYPE_COPY_PASTE));
-}
-
-TYPED_TEST(ClipboardTest, SharedBitmapWithOneNegativeSize) {
- Clipboard::ObjectMapParam placeholder_param;
- void* crash_me = reinterpret_cast<void*>(57);
- placeholder_param.resize(sizeof(crash_me));
- memcpy(&placeholder_param.front(), &crash_me, sizeof(crash_me));
-
- Clipboard::ObjectMapParam size_param;
- UnsafeSize size = {-100, 100};
- size_param.resize(sizeof(size));
- memcpy(&size_param.front(), &size, sizeof(size));
-
- Clipboard::ObjectMapParams params;
- params.push_back(placeholder_param);
- params.push_back(size_param);
-
- Clipboard::ObjectMap objects;
- objects[Clipboard::CBF_SMBITMAP] = params;
-
- this->WriteObjectsToClipboard(objects);
- EXPECT_FALSE(this->clipboard().IsFormatAvailable(
- Clipboard::GetBitmapFormatType(), CLIPBOARD_TYPE_COPY_PASTE));
-}
-
-TYPED_TEST(ClipboardTest, BitmapWithSuperSize) {
- Clipboard::ObjectMapParam placeholder_param;
- void* crash_me = reinterpret_cast<void*>(57);
- placeholder_param.resize(sizeof(crash_me));
- memcpy(&placeholder_param.front(), &crash_me, sizeof(crash_me));
-
- Clipboard::ObjectMapParam size_param;
- // Width just big enough that bytes per row won't fit in a 32-bit
- // representation.
- gfx::Size size(0x20000000, 1);
- size_param.resize(sizeof(size));
- memcpy(&size_param.front(), &size, sizeof(size));
-
- Clipboard::ObjectMapParams params;
- params.push_back(placeholder_param);
- params.push_back(size_param);
-
- Clipboard::ObjectMap objects;
- objects[Clipboard::CBF_SMBITMAP] = params;
-
- this->WriteObjectsToClipboard(objects);
- EXPECT_FALSE(this->clipboard().IsFormatAvailable(
- Clipboard::GetBitmapFormatType(), CLIPBOARD_TYPE_COPY_PASTE));
-}
-
-TYPED_TEST(ClipboardTest, BitmapWithSuperSize2) {
- Clipboard::ObjectMapParam placeholder_param;
- void* crash_me = reinterpret_cast<void*>(57);
- placeholder_param.resize(sizeof(crash_me));
- memcpy(&placeholder_param.front(), &crash_me, sizeof(crash_me));
-
- Clipboard::ObjectMapParam size_param;
- // Width and height large enough that SkBitmap::getSize() will be truncated.
- gfx::Size size(0x0fffffff, 0x0fffffff);
- size_param.resize(sizeof(size));
- memcpy(&size_param.front(), &size, sizeof(size));
-
- Clipboard::ObjectMapParams params;
- params.push_back(placeholder_param);
- params.push_back(size_param);
-
- Clipboard::ObjectMap objects;
- objects[Clipboard::CBF_SMBITMAP] = params;
-
- this->WriteObjectsToClipboard(objects);
- EXPECT_FALSE(this->clipboard().IsFormatAvailable(
- Clipboard::GetBitmapFormatType(), CLIPBOARD_TYPE_COPY_PASTE));
-}
-
TYPED_TEST(ClipboardTest, DataTest) {
const ui::Clipboard::FormatType kFormat =
ui::Clipboard::GetFormatType("chromium/x-test-format");
@@ -754,4 +602,46 @@ TYPED_TEST(ClipboardTest, GetSequenceNumber) {
}
#endif
+// Test that writing empty parameters doesn't try to dereference an empty data
+// vector. Not crashing = passing.
+TYPED_TEST(ClipboardTest, WriteTextEmptyParams) {
+ ScopedClipboardWriter scw(CLIPBOARD_TYPE_COPY_PASTE);
+ scw.WriteText(base::string16());
+}
+
+TYPED_TEST(ClipboardTest, WriteURLEmptyParams) {
+ ScopedClipboardWriter scw(CLIPBOARD_TYPE_COPY_PASTE);
+ scw.WriteURL(base::string16());
+}
+
+TYPED_TEST(ClipboardTest, WriteHTMLEmptyParams) {
+ ScopedClipboardWriter scw(CLIPBOARD_TYPE_COPY_PASTE);
+ scw.WriteHTML(base::string16(), std::string());
+}
+
+TYPED_TEST(ClipboardTest, WriteRTFEmptyParams) {
+ ScopedClipboardWriter scw(CLIPBOARD_TYPE_COPY_PASTE);
+ scw.WriteRTF(std::string());
+}
+
+TYPED_TEST(ClipboardTest, WriteBookmarkEmptyParams) {
+ ScopedClipboardWriter scw(CLIPBOARD_TYPE_COPY_PASTE);
+ scw.WriteBookmark(base::string16(), std::string());
+}
+
+TYPED_TEST(ClipboardTest, WriteHyperlinkEmptyParams) {
+ ScopedClipboardWriter scw(CLIPBOARD_TYPE_COPY_PASTE);
+ scw.WriteHyperlink(base::string16(), std::string());
+}
+
+TYPED_TEST(ClipboardTest, WritePickledData) {
+ ScopedClipboardWriter scw(CLIPBOARD_TYPE_COPY_PASTE);
+ scw.WritePickledData(Pickle(), Clipboard::GetPlainTextFormatType());
+}
+
+TYPED_TEST(ClipboardTest, WriteImageEmptyParams) {
+ ScopedClipboardWriter scw(CLIPBOARD_TYPE_COPY_PASTE);
+ scw.WriteImage(SkBitmap());
+}
+
} // namespace ui
diff --git a/ui/base/clipboard/clipboard_util_win.cc b/ui/base/clipboard/clipboard_util_win.cc
index 687f0ff..91d58a0 100644
--- a/ui/base/clipboard/clipboard_util_win.cc
+++ b/ui/base/clipboard/clipboard_util_win.cc
@@ -9,6 +9,7 @@
#include <wininet.h> // For INTERNET_MAX_URL_LENGTH.
#include "base/basictypes.h"
+#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
diff --git a/ui/base/clipboard/scoped_clipboard_writer.cc b/ui/base/clipboard/scoped_clipboard_writer.cc
index 50a7ba3..599b565 100644
--- a/ui/base/clipboard/scoped_clipboard_writer.cc
+++ b/ui/base/clipboard/scoped_clipboard_writer.cc
@@ -86,6 +86,22 @@ void ScopedClipboardWriter::WriteWebSmartPaste() {
objects_[Clipboard::CBF_WEBKIT] = Clipboard::ObjectMapParams();
}
+void ScopedClipboardWriter::WriteImage(const SkBitmap& bitmap) {
+ if (bitmap.drawsNothing()) {
+ return;
+ }
+ bitmap_ = bitmap;
+ // TODO(dcheng): This is slightly less horrible than what we used to do, but
+ // only very slightly less.
+ SkBitmap* bitmap_pointer = &bitmap_;
+ Clipboard::ObjectMapParam packed_pointer;
+ packed_pointer.resize(sizeof(bitmap_pointer));
+ *reinterpret_cast<SkBitmap**>(&*packed_pointer.begin()) = bitmap_pointer;
+ Clipboard::ObjectMapParams parameters;
+ parameters.push_back(packed_pointer);
+ objects_[Clipboard::CBF_SMBITMAP] = parameters;
+}
+
void ScopedClipboardWriter::WritePickledData(
const Pickle& pickle, const Clipboard::FormatType& format) {
std::string format_string = format.Serialize();
@@ -106,6 +122,7 @@ void ScopedClipboardWriter::WritePickledData(
void ScopedClipboardWriter::Reset() {
url_text_.clear();
objects_.clear();
+ bitmap_.reset();
}
void ScopedClipboardWriter::WriteTextOrURL(const base::string16& text,
diff --git a/ui/base/clipboard/scoped_clipboard_writer.h b/ui/base/clipboard/scoped_clipboard_writer.h
index ab799bd..ba7f1a5 100644
--- a/ui/base/clipboard/scoped_clipboard_writer.h
+++ b/ui/base/clipboard/scoped_clipboard_writer.h
@@ -14,6 +14,7 @@
#include <string>
#include "base/strings/string16.h"
+#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/ui_base_export.h"
@@ -61,10 +62,12 @@ class UI_BASE_EXPORT ScopedClipboardWriter {
void WritePickledData(const Pickle& pickle,
const Clipboard::FormatType& format);
+ void WriteImage(const SkBitmap& bitmap);
+
// Removes all objects that would be written to the clipboard.
void Reset();
- protected:
+ private:
// Converts |text| to UTF-8 and adds it to the clipboard. If it's a URL, we
// also notify the clipboard of that fact.
void WriteTextOrURL(const base::string16& text, bool is_url);
@@ -74,11 +77,12 @@ class UI_BASE_EXPORT ScopedClipboardWriter {
Clipboard::ObjectMap objects_;
const ClipboardType type_;
+ SkBitmap bitmap_;
+
// We keep around the UTF-8 text of the URL in order to pass it to
// Clipboard::DidWriteURL().
std::string url_text_;
- private:
DISALLOW_COPY_AND_ASSIGN(ScopedClipboardWriter);
};
diff --git a/ui/base/test/test_clipboard.cc b/ui/base/test/test_clipboard.cc
index df51c99..cbea7e8 100644
--- a/ui/base/test/test_clipboard.cc
+++ b/ui/base/test/test_clipboard.cc
@@ -17,10 +17,12 @@ TestClipboard::TestClipboard()
TestClipboard::~TestClipboard() {
}
-void TestClipboard::UseForCurrentThread() {
+Clipboard* TestClipboard::CreateForCurrentThread() {
base::AutoLock lock(Clipboard::clipboard_map_lock_.Get());
+ Clipboard* clipboard = new TestClipboard;
Clipboard::clipboard_map_.Get()[base::PlatformThread::CurrentId()] =
- new TestClipboard;
+ clipboard;
+ return clipboard;
}
uint64 TestClipboard::GetSequenceNumber(ClipboardType type) const {
diff --git a/ui/base/test/test_clipboard.h b/ui/base/test/test_clipboard.h
index c1701bf..58fa507 100644
--- a/ui/base/test/test_clipboard.h
+++ b/ui/base/test/test_clipboard.h
@@ -16,7 +16,10 @@ class TestClipboard : public Clipboard {
TestClipboard();
~TestClipboard() override;
- static void UseForCurrentThread();
+ // Creates and associates a TestClipboard with the current thread. When no
+ // longer needed, the returned clipboard must be freed by calling
+ // Clipboard::DestroyClipboardForCurrentThread() on the same thread.
+ static Clipboard* CreateForCurrentThread();
// Clipboard overrides.
uint64 GetSequenceNumber(ClipboardType type) const override;
diff --git a/ui/base/test/test_clipboard_unittest.cc b/ui/base/test/test_clipboard_unittest.cc
index e2f7a3b..8d3a436 100644
--- a/ui/base/test/test_clipboard_unittest.cc
+++ b/ui/base/test/test_clipboard_unittest.cc
@@ -9,10 +9,7 @@
namespace ui {
struct TestClipboardTraits {
- static Clipboard* Create() {
- TestClipboard::UseForCurrentThread();
- return Clipboard::GetForCurrentThread();
- }
+ static Clipboard* Create() { return TestClipboard::CreateForCurrentThread(); }
static void Destroy(Clipboard* clipboard) {
ASSERT_EQ(Clipboard::GetForCurrentThread(), clipboard);
diff --git a/ui/base/ui_base.gyp b/ui/base/ui_base.gyp
index ef9779d..6b64c7a 100644
--- a/ui/base/ui_base.gyp
+++ b/ui/base/ui_base.gyp
@@ -34,6 +34,7 @@
],
'export_dependent_settings': [
'../../net/net.gyp:net',
+ '../../skia/skia.gyp:skia',
'../gfx/gfx.gyp:gfx',
],
'sources' : [