1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "build/build_config.h"
9 #include "base/basictypes.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/pickle.h"
13 #include "base/run_loop.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "testing/platform_test.h"
18 #include "third_party/skia/include/core/SkBitmap.h"
19 #include "third_party/skia/include/core/SkColor.h"
20 #include "third_party/skia/include/core/SkScalar.h"
21 #include "third_party/skia/include/core/SkUnPreMultiply.h"
22 #include "ui/base/clipboard/clipboard.h"
23 #include "ui/base/clipboard/scoped_clipboard_writer.h"
24 #include "ui/gfx/size.h"
27 #include "ui/base/clipboard/clipboard_util_win.h"
30 #if defined(OS_ANDROID)
31 #include "base/android/jni_android.h"
32 #include "base/android/jni_string.h"
36 #include "ui/events/platform/platform_event_source.h"
39 using base::ASCIIToUTF16
;
40 using base::UTF8ToUTF16
;
41 using base::UTF16ToUTF8
;
45 template <typename ClipboardTraits
>
46 class ClipboardTest
: public PlatformTest
{
50 : event_source_(PlatformEventSource::CreateDefault()),
51 clipboard_(ClipboardTraits::Create()) {}
53 ClipboardTest() : clipboard_(ClipboardTraits::Create()) {}
56 ~ClipboardTest() override
{ ClipboardTraits::Destroy(clipboard_
); }
58 static void WriteObjectsToClipboard(ui::Clipboard
* clipboard
,
59 const Clipboard::ObjectMap
& objects
) {
60 clipboard
->WriteObjects(ui::CLIPBOARD_TYPE_COPY_PASTE
, objects
);
64 Clipboard
& clipboard() { return *clipboard_
; }
66 void WriteObjectsToClipboard(const Clipboard::ObjectMap
& objects
) {
67 WriteObjectsToClipboard(&clipboard(), objects
);
71 base::MessageLoopForUI message_loop_
;
73 scoped_ptr
<PlatformEventSource
> event_source_
;
75 // ui::Clipboard has a protected destructor, so scoped_ptr doesn't work here.
76 Clipboard
* const clipboard_
;
81 bool MarkupMatches(const base::string16
& expected_markup
,
82 const base::string16
& actual_markup
) {
83 return actual_markup
.find(expected_markup
) != base::string16::npos
;
88 struct PlatformClipboardTraits
{
89 static Clipboard
* Create() {
90 return Clipboard::GetForCurrentThread();
93 static void Destroy(Clipboard
* clipboard
) {
94 ASSERT_EQ(Clipboard::GetForCurrentThread(), clipboard
);
95 Clipboard::DestroyClipboardForCurrentThread();
99 TYPED_TEST_CASE(ClipboardTest
, PlatformClipboardTraits
);
101 TYPED_TEST(ClipboardTest
, ClearTest
) {
103 ScopedClipboardWriter
clipboard_writer(CLIPBOARD_TYPE_COPY_PASTE
);
104 clipboard_writer
.WriteText(ASCIIToUTF16("clear me"));
107 this->clipboard().Clear(CLIPBOARD_TYPE_COPY_PASTE
);
109 EXPECT_FALSE(this->clipboard().IsFormatAvailable(
110 Clipboard::GetPlainTextWFormatType(), CLIPBOARD_TYPE_COPY_PASTE
));
111 EXPECT_FALSE(this->clipboard().IsFormatAvailable(
112 Clipboard::GetPlainTextFormatType(), CLIPBOARD_TYPE_COPY_PASTE
));
115 TYPED_TEST(ClipboardTest
, TextTest
) {
116 base::string16
text(ASCIIToUTF16("This is a base::string16!#$")), text_result
;
117 std::string ascii_text
;
120 ScopedClipboardWriter
clipboard_writer(CLIPBOARD_TYPE_COPY_PASTE
);
121 clipboard_writer
.WriteText(text
);
124 EXPECT_TRUE(this->clipboard().IsFormatAvailable(
125 Clipboard::GetPlainTextWFormatType(), CLIPBOARD_TYPE_COPY_PASTE
));
126 EXPECT_TRUE(this->clipboard().IsFormatAvailable(
127 Clipboard::GetPlainTextFormatType(), CLIPBOARD_TYPE_COPY_PASTE
));
128 this->clipboard().ReadText(CLIPBOARD_TYPE_COPY_PASTE
, &text_result
);
130 EXPECT_EQ(text
, text_result
);
131 this->clipboard().ReadAsciiText(CLIPBOARD_TYPE_COPY_PASTE
, &ascii_text
);
132 EXPECT_EQ(UTF16ToUTF8(text
), ascii_text
);
135 TYPED_TEST(ClipboardTest
, HTMLTest
) {
136 base::string16
markup(ASCIIToUTF16("<string>Hi!</string>")), markup_result
;
137 base::string16
plain(ASCIIToUTF16("Hi!")), plain_result
;
138 std::string
url("http://www.example.com/"), url_result
;
141 ScopedClipboardWriter
clipboard_writer(CLIPBOARD_TYPE_COPY_PASTE
);
142 clipboard_writer
.WriteText(plain
);
143 clipboard_writer
.WriteHTML(markup
, url
);
146 EXPECT_TRUE(this->clipboard().IsFormatAvailable(
147 Clipboard::GetHtmlFormatType(), CLIPBOARD_TYPE_COPY_PASTE
));
149 this->clipboard().ReadHTML(CLIPBOARD_TYPE_COPY_PASTE
, &markup_result
,
150 &url_result
, &ignored
, &ignored
);
151 EXPECT_PRED2(MarkupMatches
, markup
, markup_result
);
153 // TODO(playmobil): It's not clear that non windows clipboards need to support
155 EXPECT_EQ(url
, url_result
);
156 #endif // defined(OS_WIN)
159 TYPED_TEST(ClipboardTest
, RTFTest
) {
161 "{\\rtf1\\ansi{\\fonttbl\\f0\\fswiss Helvetica;}\\f0\\pard\n"
162 "This is some {\\b bold} text.\\par\n"
166 ScopedClipboardWriter
clipboard_writer(CLIPBOARD_TYPE_COPY_PASTE
);
167 clipboard_writer
.WriteRTF(rtf
);
170 EXPECT_TRUE(this->clipboard().IsFormatAvailable(Clipboard::GetRtfFormatType(),
171 CLIPBOARD_TYPE_COPY_PASTE
));
173 this->clipboard().ReadRTF(CLIPBOARD_TYPE_COPY_PASTE
, &result
);
174 EXPECT_EQ(rtf
, result
);
177 // TODO(dnicoara) Enable test once Ozone implements clipboard support:
179 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && !defined(USE_OZONE)
180 TYPED_TEST(ClipboardTest
, MultipleBufferTest
) {
181 base::string16
text(ASCIIToUTF16("Standard")), text_result
;
182 base::string16
markup(ASCIIToUTF16("<string>Selection</string>"));
183 std::string
url("http://www.example.com/"), url_result
;
186 ScopedClipboardWriter
clipboard_writer(CLIPBOARD_TYPE_COPY_PASTE
);
187 clipboard_writer
.WriteText(text
);
191 ScopedClipboardWriter
clipboard_writer(CLIPBOARD_TYPE_SELECTION
);
192 clipboard_writer
.WriteHTML(markup
, url
);
195 EXPECT_TRUE(this->clipboard().IsFormatAvailable(
196 Clipboard::GetPlainTextFormatType(), CLIPBOARD_TYPE_COPY_PASTE
));
197 EXPECT_FALSE(this->clipboard().IsFormatAvailable(
198 Clipboard::GetPlainTextFormatType(), CLIPBOARD_TYPE_SELECTION
));
200 EXPECT_FALSE(this->clipboard().IsFormatAvailable(
201 Clipboard::GetHtmlFormatType(), CLIPBOARD_TYPE_COPY_PASTE
));
202 EXPECT_TRUE(this->clipboard().IsFormatAvailable(
203 Clipboard::GetHtmlFormatType(), CLIPBOARD_TYPE_SELECTION
));
205 this->clipboard().ReadText(CLIPBOARD_TYPE_COPY_PASTE
, &text_result
);
206 EXPECT_EQ(text
, text_result
);
209 base::string16 markup_result
;
210 this->clipboard().ReadHTML(CLIPBOARD_TYPE_SELECTION
, &markup_result
,
211 &url_result
, &ignored
, &ignored
);
212 EXPECT_PRED2(MarkupMatches
, markup
, markup_result
);
216 TYPED_TEST(ClipboardTest
, TrickyHTMLTest
) {
217 base::string16
markup(ASCIIToUTF16("<em>Bye!<!--EndFragment --></em>")),
219 std::string url
, url_result
;
220 base::string16
plain(ASCIIToUTF16("Bye!")), plain_result
;
223 ScopedClipboardWriter
clipboard_writer(CLIPBOARD_TYPE_COPY_PASTE
);
224 clipboard_writer
.WriteText(plain
);
225 clipboard_writer
.WriteHTML(markup
, url
);
228 EXPECT_TRUE(this->clipboard().IsFormatAvailable(
229 Clipboard::GetHtmlFormatType(), CLIPBOARD_TYPE_COPY_PASTE
));
231 this->clipboard().ReadHTML(CLIPBOARD_TYPE_COPY_PASTE
, &markup_result
,
232 &url_result
, &ignored
, &ignored
);
233 EXPECT_PRED2(MarkupMatches
, markup
, markup_result
);
235 // TODO(playmobil): It's not clear that non windows clipboards need to support
237 EXPECT_EQ(url
, url_result
);
238 #endif // defined(OS_WIN)
242 TYPED_TEST(ClipboardTest
, UniodeHTMLTest
) {
243 base::string16
markup(UTF8ToUTF16("<div>A \xc3\xb8 \xe6\xb0\xb4</div>")),
245 std::string url
, url_result
;
248 ScopedClipboardWriter
clipboard_writer(CLIPBOARD_TYPE_COPY_PASTE
);
249 clipboard_writer
.WriteHTML(markup
, url
);
252 EXPECT_TRUE(this->clipboard().IsFormatAvailable(
253 Clipboard::GetHtmlFormatType(), CLIPBOARD_TYPE_COPY_PASTE
));
254 uint32 fragment_start
;
256 this->clipboard().ReadHTML(CLIPBOARD_TYPE_COPY_PASTE
, &markup_result
,
257 &url_result
, &fragment_start
, &fragment_end
);
258 EXPECT_PRED2(MarkupMatches
, markup
, markup_result
);
259 EXPECT_EQ(url
, url_result
);
260 // Make sure that fragment indices were adjusted when converting.
261 EXPECT_EQ(36, fragment_start
);
262 EXPECT_EQ(52, fragment_end
);
264 #endif // defined(OS_WIN)
266 // TODO(estade): Port the following test (decide what target we use for urls)
267 #if !defined(OS_POSIX) || defined(OS_MACOSX)
268 TYPED_TEST(ClipboardTest
, BookmarkTest
) {
269 base::string16
title(ASCIIToUTF16("The Example Company")), title_result
;
270 std::string
url("http://www.example.com/"), url_result
;
273 ScopedClipboardWriter
clipboard_writer(CLIPBOARD_TYPE_COPY_PASTE
);
274 clipboard_writer
.WriteBookmark(title
, url
);
277 EXPECT_TRUE(this->clipboard().IsFormatAvailable(
278 Clipboard::GetUrlWFormatType(), CLIPBOARD_TYPE_COPY_PASTE
));
279 this->clipboard().ReadBookmark(&title_result
, &url_result
);
280 EXPECT_EQ(title
, title_result
);
281 EXPECT_EQ(url
, url_result
);
283 #endif // !defined(OS_POSIX) || defined(OS_MACOSX)
285 TYPED_TEST(ClipboardTest
, MultiFormatTest
) {
286 base::string16
text(ASCIIToUTF16("Hi!")), text_result
;
287 base::string16
markup(ASCIIToUTF16("<strong>Hi!</string>")), markup_result
;
288 std::string
url("http://www.example.com/"), url_result
;
289 std::string ascii_text
;
292 ScopedClipboardWriter
clipboard_writer(CLIPBOARD_TYPE_COPY_PASTE
);
293 clipboard_writer
.WriteHTML(markup
, url
);
294 clipboard_writer
.WriteText(text
);
297 EXPECT_TRUE(this->clipboard().IsFormatAvailable(
298 Clipboard::GetHtmlFormatType(), CLIPBOARD_TYPE_COPY_PASTE
));
299 EXPECT_TRUE(this->clipboard().IsFormatAvailable(
300 Clipboard::GetPlainTextWFormatType(), CLIPBOARD_TYPE_COPY_PASTE
));
301 EXPECT_TRUE(this->clipboard().IsFormatAvailable(
302 Clipboard::GetPlainTextFormatType(), CLIPBOARD_TYPE_COPY_PASTE
));
304 this->clipboard().ReadHTML(CLIPBOARD_TYPE_COPY_PASTE
, &markup_result
,
305 &url_result
, &ignored
, &ignored
);
306 EXPECT_PRED2(MarkupMatches
, markup
, markup_result
);
308 // TODO(playmobil): It's not clear that non windows clipboards need to support
310 EXPECT_EQ(url
, url_result
);
311 #endif // defined(OS_WIN)
312 this->clipboard().ReadText(CLIPBOARD_TYPE_COPY_PASTE
, &text_result
);
313 EXPECT_EQ(text
, text_result
);
314 this->clipboard().ReadAsciiText(CLIPBOARD_TYPE_COPY_PASTE
, &ascii_text
);
315 EXPECT_EQ(UTF16ToUTF8(text
), ascii_text
);
318 TYPED_TEST(ClipboardTest
, URLTest
) {
319 base::string16
url(ASCIIToUTF16("http://www.google.com/"));
322 ScopedClipboardWriter
clipboard_writer(CLIPBOARD_TYPE_COPY_PASTE
);
323 clipboard_writer
.WriteURL(url
);
326 EXPECT_TRUE(this->clipboard().IsFormatAvailable(
327 Clipboard::GetPlainTextWFormatType(), CLIPBOARD_TYPE_COPY_PASTE
));
328 EXPECT_TRUE(this->clipboard().IsFormatAvailable(
329 Clipboard::GetPlainTextFormatType(), CLIPBOARD_TYPE_COPY_PASTE
));
330 base::string16 text_result
;
331 this->clipboard().ReadText(CLIPBOARD_TYPE_COPY_PASTE
, &text_result
);
333 EXPECT_EQ(text_result
, url
);
335 std::string ascii_text
;
336 this->clipboard().ReadAsciiText(CLIPBOARD_TYPE_COPY_PASTE
, &ascii_text
);
337 EXPECT_EQ(UTF16ToUTF8(url
), ascii_text
);
339 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
341 this->clipboard().ReadAsciiText(CLIPBOARD_TYPE_SELECTION
, &ascii_text
);
342 EXPECT_EQ(UTF16ToUTF8(url
), ascii_text
);
346 // TODO(dcheng): The tests for copying to the clipboard also test IPC
347 // interaction... consider moving them to a different layer so we can
348 // consolidate the validation logic.
349 // Note that |bitmap_data| is not premultiplied!
350 static void TestBitmapWrite(Clipboard
* clipboard
,
351 const uint32
* bitmap_data
,
352 size_t bitmap_data_size
,
353 const gfx::Size
& size
) {
354 // Create shared memory region.
355 base::SharedMemory shared_buf
;
356 ASSERT_TRUE(shared_buf
.CreateAndMapAnonymous(bitmap_data_size
));
357 memcpy(shared_buf
.memory(), bitmap_data
, bitmap_data_size
);
358 // CBF_SMBITMAP expects premultiplied bitmap data so do that now.
359 uint32
* pixel_buffer
= static_cast<uint32
*>(shared_buf
.memory());
360 for (int j
= 0; j
< size
.height(); ++j
) {
361 for (int i
= 0; i
< size
.width(); ++i
) {
362 uint32
& pixel
= pixel_buffer
[i
+ j
* size
.width()];
363 pixel
= SkPreMultiplyColor(pixel
);
366 base::SharedMemoryHandle handle_to_share
;
367 base::ProcessHandle current_process
= base::kNullProcessHandle
;
369 current_process
= GetCurrentProcess();
371 shared_buf
.ShareToProcess(current_process
, &handle_to_share
);
372 ASSERT_TRUE(shared_buf
.Unmap());
374 // Setup data for clipboard().
375 Clipboard::ObjectMapParam placeholder_param
;
376 Clipboard::ObjectMapParam size_param
;
377 const char* size_data
= reinterpret_cast<const char*>(&size
);
378 for (size_t i
= 0; i
< sizeof(size
); ++i
)
379 size_param
.push_back(size_data
[i
]);
381 Clipboard::ObjectMapParams params
;
382 params
.push_back(placeholder_param
);
383 params
.push_back(size_param
);
385 Clipboard::ObjectMap objects
;
386 objects
[Clipboard::CBF_SMBITMAP
] = params
;
387 ASSERT_TRUE(Clipboard::ReplaceSharedMemHandle(
388 &objects
, handle_to_share
, current_process
));
390 // This is pretty ugly, but the template type parameter is irrelevant... and
391 // this test will be going away anyway.
392 ClipboardTest
<PlatformClipboardTraits
>::WriteObjectsToClipboard(clipboard
,
395 EXPECT_TRUE(clipboard
->IsFormatAvailable(Clipboard::GetBitmapFormatType(),
396 CLIPBOARD_TYPE_COPY_PASTE
));
397 const SkBitmap
& image
= clipboard
->ReadImage(CLIPBOARD_TYPE_COPY_PASTE
);
398 EXPECT_EQ(size
, gfx::Size(image
.width(), image
.height()));
399 SkAutoLockPixels
image_lock(image
);
400 for (int j
= 0; j
< image
.height(); ++j
) {
401 const uint32
* row_address
= image
.getAddr32(0, j
);
402 for (int i
= 0; i
< image
.width(); ++i
) {
403 int offset
= i
+ j
* image
.width();
404 uint32 pixel
= SkPreMultiplyColor(bitmap_data
[offset
]);
405 EXPECT_EQ(pixel
, row_address
[i
])
406 << "i = " << i
<< ", j = " << j
;
411 TYPED_TEST(ClipboardTest
, SharedBitmapTest
) {
412 const uint32 fake_bitmap_1
[] = {
413 0x46155189, 0xF6A55C8D, 0x79845674, 0xFA57BD89,
414 0x78FD46AE, 0x87C64F5A, 0x36EDC5AF, 0x4378F568,
415 0x91E9F63A, 0xC31EA14F, 0x69AB32DF, 0x643A3FD1,
418 SCOPED_TRACE("first bitmap");
419 TestBitmapWrite(&this->clipboard(), fake_bitmap_1
, sizeof(fake_bitmap_1
),
423 const uint32 fake_bitmap_2
[] = {
424 0x46155189, 0xF6A55C8D,
425 0x79845674, 0xFA57BD89,
426 0x78FD46AE, 0x87C64F5A,
427 0x36EDC5AF, 0x4378F568,
428 0x91E9F63A, 0xC31EA14F,
429 0x69AB32DF, 0x643A3FD1,
430 0xA6DF041D, 0x83046278,
433 SCOPED_TRACE("second bitmap");
434 TestBitmapWrite(&this->clipboard(), fake_bitmap_2
, sizeof(fake_bitmap_2
),
440 // A size class that just happens to have the same layout as gfx::Size!
445 COMPILE_ASSERT(sizeof(UnsafeSize
) == sizeof(gfx::Size
),
446 UnsafeSize_must_be_same_size_as_gfx_Size
);
449 TYPED_TEST(ClipboardTest
, SharedBitmapWithTwoNegativeSizes
) {
450 Clipboard::ObjectMapParam placeholder_param
;
451 void* crash_me
= reinterpret_cast<void*>(57);
452 placeholder_param
.resize(sizeof(crash_me
));
453 memcpy(&placeholder_param
.front(), &crash_me
, sizeof(crash_me
));
455 Clipboard::ObjectMapParam size_param
;
456 UnsafeSize size
= {-100, -100};
457 size_param
.resize(sizeof(size
));
458 memcpy(&size_param
.front(), &size
, sizeof(size
));
460 Clipboard::ObjectMapParams params
;
461 params
.push_back(placeholder_param
);
462 params
.push_back(size_param
);
464 Clipboard::ObjectMap objects
;
465 objects
[Clipboard::CBF_SMBITMAP
] = params
;
467 this->WriteObjectsToClipboard(objects
);
468 EXPECT_FALSE(this->clipboard().IsFormatAvailable(
469 Clipboard::GetBitmapFormatType(), CLIPBOARD_TYPE_COPY_PASTE
));
472 TYPED_TEST(ClipboardTest
, SharedBitmapWithOneNegativeSize
) {
473 Clipboard::ObjectMapParam placeholder_param
;
474 void* crash_me
= reinterpret_cast<void*>(57);
475 placeholder_param
.resize(sizeof(crash_me
));
476 memcpy(&placeholder_param
.front(), &crash_me
, sizeof(crash_me
));
478 Clipboard::ObjectMapParam size_param
;
479 UnsafeSize size
= {-100, 100};
480 size_param
.resize(sizeof(size
));
481 memcpy(&size_param
.front(), &size
, sizeof(size
));
483 Clipboard::ObjectMapParams params
;
484 params
.push_back(placeholder_param
);
485 params
.push_back(size_param
);
487 Clipboard::ObjectMap objects
;
488 objects
[Clipboard::CBF_SMBITMAP
] = params
;
490 this->WriteObjectsToClipboard(objects
);
491 EXPECT_FALSE(this->clipboard().IsFormatAvailable(
492 Clipboard::GetBitmapFormatType(), CLIPBOARD_TYPE_COPY_PASTE
));
495 TYPED_TEST(ClipboardTest
, BitmapWithSuperSize
) {
496 Clipboard::ObjectMapParam placeholder_param
;
497 void* crash_me
= reinterpret_cast<void*>(57);
498 placeholder_param
.resize(sizeof(crash_me
));
499 memcpy(&placeholder_param
.front(), &crash_me
, sizeof(crash_me
));
501 Clipboard::ObjectMapParam size_param
;
502 // Width just big enough that bytes per row won't fit in a 32-bit
504 gfx::Size
size(0x20000000, 1);
505 size_param
.resize(sizeof(size
));
506 memcpy(&size_param
.front(), &size
, sizeof(size
));
508 Clipboard::ObjectMapParams params
;
509 params
.push_back(placeholder_param
);
510 params
.push_back(size_param
);
512 Clipboard::ObjectMap objects
;
513 objects
[Clipboard::CBF_SMBITMAP
] = params
;
515 this->WriteObjectsToClipboard(objects
);
516 EXPECT_FALSE(this->clipboard().IsFormatAvailable(
517 Clipboard::GetBitmapFormatType(), CLIPBOARD_TYPE_COPY_PASTE
));
520 TYPED_TEST(ClipboardTest
, BitmapWithSuperSize2
) {
521 Clipboard::ObjectMapParam placeholder_param
;
522 void* crash_me
= reinterpret_cast<void*>(57);
523 placeholder_param
.resize(sizeof(crash_me
));
524 memcpy(&placeholder_param
.front(), &crash_me
, sizeof(crash_me
));
526 Clipboard::ObjectMapParam size_param
;
527 // Width and height large enough that SkBitmap::getSize() will be truncated.
528 gfx::Size
size(0x0fffffff, 0x0fffffff);
529 size_param
.resize(sizeof(size
));
530 memcpy(&size_param
.front(), &size
, sizeof(size
));
532 Clipboard::ObjectMapParams params
;
533 params
.push_back(placeholder_param
);
534 params
.push_back(size_param
);
536 Clipboard::ObjectMap objects
;
537 objects
[Clipboard::CBF_SMBITMAP
] = params
;
539 this->WriteObjectsToClipboard(objects
);
540 EXPECT_FALSE(this->clipboard().IsFormatAvailable(
541 Clipboard::GetBitmapFormatType(), CLIPBOARD_TYPE_COPY_PASTE
));
544 TYPED_TEST(ClipboardTest
, DataTest
) {
545 const ui::Clipboard::FormatType kFormat
=
546 ui::Clipboard::GetFormatType("chromium/x-test-format");
547 std::string
payload("test string");
549 write_pickle
.WriteString(payload
);
552 ScopedClipboardWriter
clipboard_writer(CLIPBOARD_TYPE_COPY_PASTE
);
553 clipboard_writer
.WritePickledData(write_pickle
, kFormat
);
557 this->clipboard().IsFormatAvailable(kFormat
, CLIPBOARD_TYPE_COPY_PASTE
));
559 this->clipboard().ReadData(kFormat
, &output
);
560 ASSERT_FALSE(output
.empty());
562 Pickle
read_pickle(output
.data(), output
.size());
563 PickleIterator
iter(read_pickle
);
564 std::string unpickled_string
;
565 ASSERT_TRUE(read_pickle
.ReadString(&iter
, &unpickled_string
));
566 EXPECT_EQ(payload
, unpickled_string
);
569 TYPED_TEST(ClipboardTest
, MultipleDataTest
) {
570 const ui::Clipboard::FormatType kFormat1
=
571 ui::Clipboard::GetFormatType("chromium/x-test-format1");
572 std::string
payload1("test string1");
573 Pickle write_pickle1
;
574 write_pickle1
.WriteString(payload1
);
576 const ui::Clipboard::FormatType kFormat2
=
577 ui::Clipboard::GetFormatType("chromium/x-test-format2");
578 std::string
payload2("test string2");
579 Pickle write_pickle2
;
580 write_pickle2
.WriteString(payload2
);
583 ScopedClipboardWriter
clipboard_writer(CLIPBOARD_TYPE_COPY_PASTE
);
584 clipboard_writer
.WritePickledData(write_pickle1
, kFormat1
);
585 // overwrite the previous pickle for fun
586 clipboard_writer
.WritePickledData(write_pickle2
, kFormat2
);
590 this->clipboard().IsFormatAvailable(kFormat2
, CLIPBOARD_TYPE_COPY_PASTE
));
594 this->clipboard().ReadData(kFormat2
, &output2
);
595 ASSERT_FALSE(output2
.empty());
597 Pickle
read_pickle2(output2
.data(), output2
.size());
598 PickleIterator
iter2(read_pickle2
);
599 std::string unpickled_string2
;
600 ASSERT_TRUE(read_pickle2
.ReadString(&iter2
, &unpickled_string2
));
601 EXPECT_EQ(payload2
, unpickled_string2
);
604 ScopedClipboardWriter
clipboard_writer(CLIPBOARD_TYPE_COPY_PASTE
);
605 clipboard_writer
.WritePickledData(write_pickle2
, kFormat2
);
606 // overwrite the previous pickle for fun
607 clipboard_writer
.WritePickledData(write_pickle1
, kFormat1
);
611 this->clipboard().IsFormatAvailable(kFormat1
, CLIPBOARD_TYPE_COPY_PASTE
));
615 this->clipboard().ReadData(kFormat1
, &output1
);
616 ASSERT_FALSE(output1
.empty());
618 Pickle
read_pickle1(output1
.data(), output1
.size());
619 PickleIterator
iter1(read_pickle1
);
620 std::string unpickled_string1
;
621 ASSERT_TRUE(read_pickle1
.ReadString(&iter1
, &unpickled_string1
));
622 EXPECT_EQ(payload1
, unpickled_string1
);
625 #if !defined(OS_MACOSX) && !defined(OS_ANDROID)
626 TYPED_TEST(ClipboardTest
, HyperlinkTest
) {
627 const std::string
kTitle("The <Example> Company's \"home page\"");
628 const std::string
kUrl("http://www.example.com?x=3<=3#\"'<>");
629 const std::string
kExpectedHtml(
630 "<a href=\"http://www.example.com?x=3&lt=3#"'<>\">"
631 "The <Example> Company's "home page"</a>");
633 std::string url_result
;
634 base::string16 html_result
;
636 ScopedClipboardWriter
clipboard_writer(CLIPBOARD_TYPE_COPY_PASTE
);
637 clipboard_writer
.WriteHyperlink(ASCIIToUTF16(kTitle
), kUrl
);
640 EXPECT_TRUE(this->clipboard().IsFormatAvailable(
641 Clipboard::GetHtmlFormatType(), CLIPBOARD_TYPE_COPY_PASTE
));
643 this->clipboard().ReadHTML(CLIPBOARD_TYPE_COPY_PASTE
, &html_result
,
644 &url_result
, &ignored
, &ignored
);
645 EXPECT_PRED2(MarkupMatches
, ASCIIToUTF16(kExpectedHtml
), html_result
);
649 TYPED_TEST(ClipboardTest
, WebSmartPasteTest
) {
651 ScopedClipboardWriter
clipboard_writer(CLIPBOARD_TYPE_COPY_PASTE
);
652 clipboard_writer
.WriteWebSmartPaste();
655 EXPECT_TRUE(this->clipboard().IsFormatAvailable(
656 Clipboard::GetWebKitSmartPasteFormatType(), CLIPBOARD_TYPE_COPY_PASTE
));
659 #if defined(OS_WIN) // Windows only tests.
660 void HtmlTestHelper(const std::string
& cf_html
,
661 const std::string
& expected_html
) {
663 ClipboardUtil::CFHtmlToHtml(cf_html
, &html
, NULL
);
664 EXPECT_EQ(html
, expected_html
);
667 TYPED_TEST(ClipboardTest
, HtmlTest
) {
668 // Test converting from CF_HTML format data with <!--StartFragment--> and
669 // <!--EndFragment--> comments, like from MS Word.
670 HtmlTestHelper("Version:1.0\r\n"
671 "StartHTML:0000000105\r\n"
672 "EndHTML:0000000199\r\n"
673 "StartFragment:0000000123\r\n"
674 "EndFragment:0000000161\r\n"
678 "<!--StartFragment-->\r\n"
682 "<!--EndFragment-->\r\n"
687 // Test converting from CF_HTML format data without <!--StartFragment--> and
688 // <!--EndFragment--> comments, like from OpenOffice Writer.
689 HtmlTestHelper("Version:1.0\r\n"
690 "StartHTML:0000000105\r\n"
691 "EndHTML:0000000151\r\n"
692 "StartFragment:0000000121\r\n"
693 "EndFragment:0000000131\r\n"
701 #endif // defined(OS_WIN)
703 // Test writing all formats we have simultaneously.
704 TYPED_TEST(ClipboardTest
, WriteEverything
) {
706 ScopedClipboardWriter
writer(CLIPBOARD_TYPE_COPY_PASTE
);
707 writer
.WriteText(UTF8ToUTF16("foo"));
708 writer
.WriteURL(UTF8ToUTF16("foo"));
709 writer
.WriteHTML(UTF8ToUTF16("foo"), "bar");
710 writer
.WriteBookmark(UTF8ToUTF16("foo"), "bar");
711 writer
.WriteHyperlink(ASCIIToUTF16("foo"), "bar");
712 writer
.WriteWebSmartPaste();
713 // Left out: WriteFile, WriteFiles, WriteBitmapFromPixels, WritePickledData.
716 // Passes if we don't crash.
719 // TODO(dcheng): Fix this test for Android. It's rather involved, since the
720 // clipboard change listener is posted to the Java message loop, and spinning
721 // that loop from C++ to trigger the callback in the test requires a non-trivial
722 // amount of additional work.
723 #if !defined(OS_ANDROID)
724 // Simple test that the sequence number appears to change when the clipboard is
726 // TODO(dcheng): Add a version to test CLIPBOARD_TYPE_SELECTION.
727 TYPED_TEST(ClipboardTest
, GetSequenceNumber
) {
728 const uint64 first_sequence_number
=
729 this->clipboard().GetSequenceNumber(CLIPBOARD_TYPE_COPY_PASTE
);
732 ScopedClipboardWriter
writer(CLIPBOARD_TYPE_COPY_PASTE
);
733 writer
.WriteText(UTF8ToUTF16("World"));
736 // On some platforms, the sequence number is updated by a UI callback so pump
737 // the message loop to make sure we get the notification.
738 base::RunLoop().RunUntilIdle();
740 const uint64 second_sequence_number
=
741 this->clipboard().GetSequenceNumber(CLIPBOARD_TYPE_COPY_PASTE
);
743 EXPECT_NE(first_sequence_number
, second_sequence_number
);
747 #if defined(OS_ANDROID)
749 // Test that if another application writes some text to the pasteboard the
750 // clipboard properly invalidates other types.
751 TYPED_TEST(ClipboardTest
, InternalClipboardInvalidation
) {
752 // Write a Webkit smart paste tag to our clipboard.
754 ScopedClipboardWriter
clipboard_writer(CLIPBOARD_TYPE_COPY_PASTE
);
755 clipboard_writer
.WriteWebSmartPaste();
757 EXPECT_TRUE(this->clipboard().IsFormatAvailable(
758 Clipboard::GetWebKitSmartPasteFormatType(), CLIPBOARD_TYPE_COPY_PASTE
));
761 // Simulate that another application copied something in the Clipboard
763 std::string
new_value("Some text copied by some other app");
764 using base::android::ConvertUTF8ToJavaString
;
765 using base::android::MethodID
;
766 using base::android::ScopedJavaLocalRef
;
768 JNIEnv
* env
= base::android::AttachCurrentThread();
771 jobject context
= base::android::GetApplicationContext();
772 ASSERT_TRUE(context
);
774 ScopedJavaLocalRef
<jclass
> context_class
=
775 base::android::GetClass(env
, "android/content/Context");
777 jmethodID get_system_service
= MethodID::Get
<MethodID::TYPE_INSTANCE
>(
778 env
, context_class
.obj(), "getSystemService",
779 "(Ljava/lang/String;)Ljava/lang/Object;");
781 // Retrieve the system service.
782 ScopedJavaLocalRef
<jstring
> service_name
= ConvertUTF8ToJavaString(
784 ScopedJavaLocalRef
<jobject
> clipboard_manager(
785 env
, env
->CallObjectMethod(
786 context
, get_system_service
, service_name
.obj()));
787 ASSERT_TRUE(clipboard_manager
.obj() && !base::android::ClearException(env
));
789 ScopedJavaLocalRef
<jclass
> clipboard_class
=
790 base::android::GetClass(env
, "android/text/ClipboardManager");
791 jmethodID set_text
= MethodID::Get
<MethodID::TYPE_INSTANCE
>(
792 env
, clipboard_class
.obj(), "setText", "(Ljava/lang/CharSequence;)V");
793 ScopedJavaLocalRef
<jstring
> new_value_string
= ConvertUTF8ToJavaString(
794 env
, new_value
.c_str());
796 // Will need to call toString as CharSequence is not always a String.
797 env
->CallVoidMethod(clipboard_manager
.obj(),
799 new_value_string
.obj());
801 // The WebKit smart paste tag should now be gone.
802 EXPECT_FALSE(this->clipboard().IsFormatAvailable(
803 Clipboard::GetWebKitSmartPasteFormatType(), CLIPBOARD_TYPE_COPY_PASTE
));
805 // Make sure some text is available
806 EXPECT_TRUE(this->clipboard().IsFormatAvailable(
807 Clipboard::GetPlainTextWFormatType(), CLIPBOARD_TYPE_COPY_PASTE
));
809 // Make sure the text is what we inserted while simulating the other app
810 std::string contents
;
811 this->clipboard().ReadAsciiText(CLIPBOARD_TYPE_COPY_PASTE
, &contents
);
812 EXPECT_EQ(contents
, new_value
);