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 class ClipboardTest
: public PlatformTest
{
48 ClipboardTest() : event_source_(ui::PlatformEventSource::CreateDefault()) {}
53 static void WriteObjectsToClipboard(ui::Clipboard
* clipboard
,
54 const Clipboard::ObjectMap
& objects
) {
55 clipboard
->WriteObjects(ui::CLIPBOARD_TYPE_COPY_PASTE
, objects
);
59 Clipboard
& clipboard() { return clipboard_
; }
61 void WriteObjectsToClipboard(const Clipboard::ObjectMap
& objects
) {
62 WriteObjectsToClipboard(&clipboard(), objects
);
66 base::MessageLoopForUI message_loop_
;
68 scoped_ptr
<PlatformEventSource
> event_source_
;
75 bool MarkupMatches(const base::string16
& expected_markup
,
76 const base::string16
& actual_markup
) {
77 return actual_markup
.find(expected_markup
) != base::string16::npos
;
82 TEST_F(ClipboardTest
, ClearTest
) {
84 ScopedClipboardWriter
clipboard_writer(&clipboard(),
85 CLIPBOARD_TYPE_COPY_PASTE
);
86 clipboard_writer
.WriteText(ASCIIToUTF16("clear me"));
89 clipboard().Clear(CLIPBOARD_TYPE_COPY_PASTE
);
91 EXPECT_FALSE(clipboard().IsFormatAvailable(
92 Clipboard::GetPlainTextWFormatType(), CLIPBOARD_TYPE_COPY_PASTE
));
93 EXPECT_FALSE(clipboard().IsFormatAvailable(
94 Clipboard::GetPlainTextFormatType(), CLIPBOARD_TYPE_COPY_PASTE
));
97 TEST_F(ClipboardTest
, TextTest
) {
98 base::string16
text(ASCIIToUTF16("This is a base::string16!#$")), text_result
;
99 std::string ascii_text
;
102 ScopedClipboardWriter
clipboard_writer(&clipboard(),
103 CLIPBOARD_TYPE_COPY_PASTE
);
104 clipboard_writer
.WriteText(text
);
107 EXPECT_TRUE(clipboard().IsFormatAvailable(
108 Clipboard::GetPlainTextWFormatType(), CLIPBOARD_TYPE_COPY_PASTE
));
109 EXPECT_TRUE(clipboard().IsFormatAvailable(Clipboard::GetPlainTextFormatType(),
110 CLIPBOARD_TYPE_COPY_PASTE
));
111 clipboard().ReadText(CLIPBOARD_TYPE_COPY_PASTE
, &text_result
);
113 EXPECT_EQ(text
, text_result
);
114 clipboard().ReadAsciiText(CLIPBOARD_TYPE_COPY_PASTE
, &ascii_text
);
115 EXPECT_EQ(UTF16ToUTF8(text
), ascii_text
);
118 TEST_F(ClipboardTest
, HTMLTest
) {
119 base::string16
markup(ASCIIToUTF16("<string>Hi!</string>")), markup_result
;
120 base::string16
plain(ASCIIToUTF16("Hi!")), plain_result
;
121 std::string
url("http://www.example.com/"), url_result
;
124 ScopedClipboardWriter
clipboard_writer(&clipboard(),
125 CLIPBOARD_TYPE_COPY_PASTE
);
126 clipboard_writer
.WriteText(plain
);
127 clipboard_writer
.WriteHTML(markup
, url
);
130 EXPECT_TRUE(clipboard().IsFormatAvailable(Clipboard::GetHtmlFormatType(),
131 CLIPBOARD_TYPE_COPY_PASTE
));
133 clipboard().ReadHTML(CLIPBOARD_TYPE_COPY_PASTE
, &markup_result
, &url_result
,
135 EXPECT_PRED2(MarkupMatches
, markup
, markup_result
);
137 // TODO(playmobil): It's not clear that non windows clipboards need to support
139 EXPECT_EQ(url
, url_result
);
140 #endif // defined(OS_WIN)
143 TEST_F(ClipboardTest
, RTFTest
) {
145 "{\\rtf1\\ansi{\\fonttbl\\f0\\fswiss Helvetica;}\\f0\\pard\n"
146 "This is some {\\b bold} text.\\par\n"
150 ScopedClipboardWriter
clipboard_writer(&clipboard(),
151 CLIPBOARD_TYPE_COPY_PASTE
);
152 clipboard_writer
.WriteRTF(rtf
);
155 EXPECT_TRUE(clipboard().IsFormatAvailable(Clipboard::GetRtfFormatType(),
156 CLIPBOARD_TYPE_COPY_PASTE
));
158 clipboard().ReadRTF(CLIPBOARD_TYPE_COPY_PASTE
, &result
);
159 EXPECT_EQ(rtf
, result
);
162 // TODO(dnicoara) Enable test once Ozone implements clipboard support:
164 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && !defined(USE_OZONE)
165 TEST_F(ClipboardTest
, MultipleBufferTest
) {
166 base::string16
text(ASCIIToUTF16("Standard")), text_result
;
167 base::string16
markup(ASCIIToUTF16("<string>Selection</string>"));
168 std::string
url("http://www.example.com/"), url_result
;
171 ScopedClipboardWriter
clipboard_writer(&clipboard(),
172 CLIPBOARD_TYPE_COPY_PASTE
);
173 clipboard_writer
.WriteText(text
);
177 ScopedClipboardWriter
clipboard_writer(&clipboard(),
178 CLIPBOARD_TYPE_SELECTION
);
179 clipboard_writer
.WriteHTML(markup
, url
);
182 EXPECT_TRUE(clipboard().IsFormatAvailable(Clipboard::GetPlainTextFormatType(),
183 CLIPBOARD_TYPE_COPY_PASTE
));
184 EXPECT_FALSE(clipboard().IsFormatAvailable(
185 Clipboard::GetPlainTextFormatType(),
186 CLIPBOARD_TYPE_SELECTION
));
188 EXPECT_FALSE(clipboard().IsFormatAvailable(Clipboard::GetHtmlFormatType(),
189 CLIPBOARD_TYPE_COPY_PASTE
));
190 EXPECT_TRUE(clipboard().IsFormatAvailable(Clipboard::GetHtmlFormatType(),
191 CLIPBOARD_TYPE_SELECTION
));
193 clipboard().ReadText(CLIPBOARD_TYPE_COPY_PASTE
, &text_result
);
194 EXPECT_EQ(text
, text_result
);
197 base::string16 markup_result
;
198 clipboard().ReadHTML(CLIPBOARD_TYPE_SELECTION
,
203 EXPECT_PRED2(MarkupMatches
, markup
, markup_result
);
207 TEST_F(ClipboardTest
, TrickyHTMLTest
) {
208 base::string16
markup(ASCIIToUTF16("<em>Bye!<!--EndFragment --></em>")),
210 std::string url
, url_result
;
211 base::string16
plain(ASCIIToUTF16("Bye!")), plain_result
;
214 ScopedClipboardWriter
clipboard_writer(&clipboard(),
215 CLIPBOARD_TYPE_COPY_PASTE
);
216 clipboard_writer
.WriteText(plain
);
217 clipboard_writer
.WriteHTML(markup
, url
);
220 EXPECT_TRUE(clipboard().IsFormatAvailable(Clipboard::GetHtmlFormatType(),
221 CLIPBOARD_TYPE_COPY_PASTE
));
223 clipboard().ReadHTML(CLIPBOARD_TYPE_COPY_PASTE
, &markup_result
, &url_result
,
225 EXPECT_PRED2(MarkupMatches
, markup
, markup_result
);
227 // TODO(playmobil): It's not clear that non windows clipboards need to support
229 EXPECT_EQ(url
, url_result
);
230 #endif // defined(OS_WIN)
234 TEST_F(ClipboardTest
, UniodeHTMLTest
) {
235 base::string16
markup(UTF8ToUTF16("<div>A \xc3\xb8 \xe6\xb0\xb4</div>")),
237 std::string url
, url_result
;
240 ScopedClipboardWriter
clipboard_writer(&clipboard(),
241 CLIPBOARD_TYPE_COPY_PASTE
);
242 clipboard_writer
.WriteHTML(markup
, url
);
245 EXPECT_TRUE(clipboard().IsFormatAvailable(Clipboard::GetHtmlFormatType(),
246 CLIPBOARD_TYPE_COPY_PASTE
));
247 uint32 fragment_start
;
249 clipboard().ReadHTML(CLIPBOARD_TYPE_COPY_PASTE
, &markup_result
, &url_result
,
250 &fragment_start
, &fragment_end
);
251 EXPECT_PRED2(MarkupMatches
, markup
, markup_result
);
252 EXPECT_EQ(url
, url_result
);
253 // Make sure that fragment indices were adjusted when converting.
254 EXPECT_EQ(36, fragment_start
);
255 EXPECT_EQ(52, fragment_end
);
257 #endif // defined(OS_WIN)
259 // TODO(estade): Port the following test (decide what target we use for urls)
260 #if !defined(OS_POSIX) || defined(OS_MACOSX)
261 TEST_F(ClipboardTest
, BookmarkTest
) {
262 base::string16
title(ASCIIToUTF16("The Example Company")), title_result
;
263 std::string
url("http://www.example.com/"), url_result
;
266 ScopedClipboardWriter
clipboard_writer(&clipboard(),
267 CLIPBOARD_TYPE_COPY_PASTE
);
268 clipboard_writer
.WriteBookmark(title
, url
);
271 EXPECT_TRUE(clipboard().IsFormatAvailable(Clipboard::GetUrlWFormatType(),
272 CLIPBOARD_TYPE_COPY_PASTE
));
273 clipboard().ReadBookmark(&title_result
, &url_result
);
274 EXPECT_EQ(title
, title_result
);
275 EXPECT_EQ(url
, url_result
);
277 #endif // defined(OS_WIN)
279 TEST_F(ClipboardTest
, MultiFormatTest
) {
280 base::string16
text(ASCIIToUTF16("Hi!")), text_result
;
281 base::string16
markup(ASCIIToUTF16("<strong>Hi!</string>")), markup_result
;
282 std::string
url("http://www.example.com/"), url_result
;
283 std::string ascii_text
;
286 ScopedClipboardWriter
clipboard_writer(&clipboard(),
287 CLIPBOARD_TYPE_COPY_PASTE
);
288 clipboard_writer
.WriteHTML(markup
, url
);
289 clipboard_writer
.WriteText(text
);
292 EXPECT_TRUE(clipboard().IsFormatAvailable(Clipboard::GetHtmlFormatType(),
293 CLIPBOARD_TYPE_COPY_PASTE
));
294 EXPECT_TRUE(clipboard().IsFormatAvailable(
295 Clipboard::GetPlainTextWFormatType(), CLIPBOARD_TYPE_COPY_PASTE
));
296 EXPECT_TRUE(clipboard().IsFormatAvailable(
297 Clipboard::GetPlainTextFormatType(), CLIPBOARD_TYPE_COPY_PASTE
));
299 clipboard().ReadHTML(CLIPBOARD_TYPE_COPY_PASTE
, &markup_result
, &url_result
,
301 EXPECT_PRED2(MarkupMatches
, markup
, markup_result
);
303 // TODO(playmobil): It's not clear that non windows clipboards need to support
305 EXPECT_EQ(url
, url_result
);
306 #endif // defined(OS_WIN)
307 clipboard().ReadText(CLIPBOARD_TYPE_COPY_PASTE
, &text_result
);
308 EXPECT_EQ(text
, text_result
);
309 clipboard().ReadAsciiText(CLIPBOARD_TYPE_COPY_PASTE
, &ascii_text
);
310 EXPECT_EQ(UTF16ToUTF8(text
), ascii_text
);
313 TEST_F(ClipboardTest
, URLTest
) {
314 base::string16
url(ASCIIToUTF16("http://www.google.com/"));
317 ScopedClipboardWriter
clipboard_writer(&clipboard(),
318 CLIPBOARD_TYPE_COPY_PASTE
);
319 clipboard_writer
.WriteURL(url
);
322 EXPECT_TRUE(clipboard().IsFormatAvailable(
323 Clipboard::GetPlainTextWFormatType(), CLIPBOARD_TYPE_COPY_PASTE
));
324 EXPECT_TRUE(clipboard().IsFormatAvailable(Clipboard::GetPlainTextFormatType(),
325 CLIPBOARD_TYPE_COPY_PASTE
));
326 base::string16 text_result
;
327 clipboard().ReadText(CLIPBOARD_TYPE_COPY_PASTE
, &text_result
);
329 EXPECT_EQ(text_result
, url
);
331 std::string ascii_text
;
332 clipboard().ReadAsciiText(CLIPBOARD_TYPE_COPY_PASTE
, &ascii_text
);
333 EXPECT_EQ(UTF16ToUTF8(url
), ascii_text
);
335 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
337 clipboard().ReadAsciiText(CLIPBOARD_TYPE_SELECTION
, &ascii_text
);
338 EXPECT_EQ(UTF16ToUTF8(url
), ascii_text
);
342 // TODO(dcheng): The tests for copying to the clipboard also test IPC
343 // interaction... consider moving them to a different layer so we can
344 // consolidate the validation logic.
345 // Note that |bitmap_data| is not premultiplied!
346 static void TestBitmapWrite(Clipboard
* clipboard
,
347 const uint32
* bitmap_data
,
348 size_t bitmap_data_size
,
349 const gfx::Size
& size
) {
350 // Create shared memory region.
351 base::SharedMemory shared_buf
;
352 ASSERT_TRUE(shared_buf
.CreateAndMapAnonymous(bitmap_data_size
));
353 memcpy(shared_buf
.memory(), bitmap_data
, bitmap_data_size
);
354 // CBF_SMBITMAP expects premultiplied bitmap data so do that now.
355 uint32
* pixel_buffer
= static_cast<uint32
*>(shared_buf
.memory());
356 for (int j
= 0; j
< size
.height(); ++j
) {
357 for (int i
= 0; i
< size
.width(); ++i
) {
358 uint32
& pixel
= pixel_buffer
[i
+ j
* size
.width()];
359 pixel
= SkPreMultiplyColor(pixel
);
362 base::SharedMemoryHandle handle_to_share
;
363 base::ProcessHandle current_process
= base::kNullProcessHandle
;
365 current_process
= GetCurrentProcess();
367 shared_buf
.ShareToProcess(current_process
, &handle_to_share
);
368 ASSERT_TRUE(shared_buf
.Unmap());
370 // Setup data for clipboard().
371 Clipboard::ObjectMapParam placeholder_param
;
372 Clipboard::ObjectMapParam size_param
;
373 const char* size_data
= reinterpret_cast<const char*>(&size
);
374 for (size_t i
= 0; i
< sizeof(size
); ++i
)
375 size_param
.push_back(size_data
[i
]);
377 Clipboard::ObjectMapParams params
;
378 params
.push_back(placeholder_param
);
379 params
.push_back(size_param
);
381 Clipboard::ObjectMap objects
;
382 objects
[Clipboard::CBF_SMBITMAP
] = params
;
383 ASSERT_TRUE(Clipboard::ReplaceSharedMemHandle(
384 &objects
, handle_to_share
, current_process
));
386 ClipboardTest::WriteObjectsToClipboard(clipboard
, objects
);
388 EXPECT_TRUE(clipboard
->IsFormatAvailable(Clipboard::GetBitmapFormatType(),
389 CLIPBOARD_TYPE_COPY_PASTE
));
390 const SkBitmap
& image
= clipboard
->ReadImage(CLIPBOARD_TYPE_COPY_PASTE
);
391 EXPECT_EQ(size
, gfx::Size(image
.width(), image
.height()));
392 SkAutoLockPixels
image_lock(image
);
393 for (int j
= 0; j
< image
.height(); ++j
) {
394 const uint32
* row_address
= image
.getAddr32(0, j
);
395 for (int i
= 0; i
< image
.width(); ++i
) {
396 int offset
= i
+ j
* image
.width();
397 uint32 pixel
= SkPreMultiplyColor(bitmap_data
[offset
]);
398 EXPECT_EQ(pixel
, row_address
[i
])
399 << "i = " << i
<< ", j = " << j
;
404 TEST_F(ClipboardTest
, SharedBitmapTest
) {
405 const uint32 fake_bitmap_1
[] = {
406 0x46155189, 0xF6A55C8D, 0x79845674, 0xFA57BD89,
407 0x78FD46AE, 0x87C64F5A, 0x36EDC5AF, 0x4378F568,
408 0x91E9F63A, 0xC31EA14F, 0x69AB32DF, 0x643A3FD1,
411 SCOPED_TRACE("first bitmap");
413 &clipboard(), fake_bitmap_1
, sizeof(fake_bitmap_1
), gfx::Size(4, 3));
416 const uint32 fake_bitmap_2
[] = {
417 0x46155189, 0xF6A55C8D,
418 0x79845674, 0xFA57BD89,
419 0x78FD46AE, 0x87C64F5A,
420 0x36EDC5AF, 0x4378F568,
421 0x91E9F63A, 0xC31EA14F,
422 0x69AB32DF, 0x643A3FD1,
423 0xA6DF041D, 0x83046278,
426 SCOPED_TRACE("second bitmap");
428 &clipboard(), fake_bitmap_2
, sizeof(fake_bitmap_2
), gfx::Size(2, 7));
433 // A size class that just happens to have the same layout as gfx::Size!
438 COMPILE_ASSERT(sizeof(UnsafeSize
) == sizeof(gfx::Size
),
439 UnsafeSize_must_be_same_size_as_gfx_Size
);
442 TEST_F(ClipboardTest
, SharedBitmapWithTwoNegativeSizes
) {
443 Clipboard::ObjectMapParam placeholder_param
;
444 void* crash_me
= reinterpret_cast<void*>(57);
445 placeholder_param
.resize(sizeof(crash_me
));
446 memcpy(&placeholder_param
.front(), &crash_me
, sizeof(crash_me
));
448 Clipboard::ObjectMapParam size_param
;
449 UnsafeSize size
= {-100, -100};
450 size_param
.resize(sizeof(size
));
451 memcpy(&size_param
.front(), &size
, sizeof(size
));
453 Clipboard::ObjectMapParams params
;
454 params
.push_back(placeholder_param
);
455 params
.push_back(size_param
);
457 Clipboard::ObjectMap objects
;
458 objects
[Clipboard::CBF_SMBITMAP
] = params
;
460 WriteObjectsToClipboard(objects
);
461 EXPECT_FALSE(clipboard().IsFormatAvailable(Clipboard::GetBitmapFormatType(),
462 CLIPBOARD_TYPE_COPY_PASTE
));
465 TEST_F(ClipboardTest
, SharedBitmapWithOneNegativeSize
) {
466 Clipboard::ObjectMapParam placeholder_param
;
467 void* crash_me
= reinterpret_cast<void*>(57);
468 placeholder_param
.resize(sizeof(crash_me
));
469 memcpy(&placeholder_param
.front(), &crash_me
, sizeof(crash_me
));
471 Clipboard::ObjectMapParam size_param
;
472 UnsafeSize size
= {-100, 100};
473 size_param
.resize(sizeof(size
));
474 memcpy(&size_param
.front(), &size
, sizeof(size
));
476 Clipboard::ObjectMapParams params
;
477 params
.push_back(placeholder_param
);
478 params
.push_back(size_param
);
480 Clipboard::ObjectMap objects
;
481 objects
[Clipboard::CBF_SMBITMAP
] = params
;
483 WriteObjectsToClipboard(objects
);
484 EXPECT_FALSE(clipboard().IsFormatAvailable(Clipboard::GetBitmapFormatType(),
485 CLIPBOARD_TYPE_COPY_PASTE
));
488 TEST_F(ClipboardTest
, BitmapWithSuperSize
) {
489 Clipboard::ObjectMapParam placeholder_param
;
490 void* crash_me
= reinterpret_cast<void*>(57);
491 placeholder_param
.resize(sizeof(crash_me
));
492 memcpy(&placeholder_param
.front(), &crash_me
, sizeof(crash_me
));
494 Clipboard::ObjectMapParam size_param
;
495 // Width just big enough that bytes per row won't fit in a 32-bit
497 gfx::Size
size(0x20000000, 1);
498 size_param
.resize(sizeof(size
));
499 memcpy(&size_param
.front(), &size
, sizeof(size
));
501 Clipboard::ObjectMapParams params
;
502 params
.push_back(placeholder_param
);
503 params
.push_back(size_param
);
505 Clipboard::ObjectMap objects
;
506 objects
[Clipboard::CBF_SMBITMAP
] = params
;
508 WriteObjectsToClipboard(objects
);
509 EXPECT_FALSE(clipboard().IsFormatAvailable(Clipboard::GetBitmapFormatType(),
510 CLIPBOARD_TYPE_COPY_PASTE
));
513 TEST_F(ClipboardTest
, BitmapWithSuperSize2
) {
514 Clipboard::ObjectMapParam placeholder_param
;
515 void* crash_me
= reinterpret_cast<void*>(57);
516 placeholder_param
.resize(sizeof(crash_me
));
517 memcpy(&placeholder_param
.front(), &crash_me
, sizeof(crash_me
));
519 Clipboard::ObjectMapParam size_param
;
520 // Width and height large enough that SkBitmap::getSize() will be truncated.
521 gfx::Size
size(0x0fffffff, 0x0fffffff);
522 size_param
.resize(sizeof(size
));
523 memcpy(&size_param
.front(), &size
, sizeof(size
));
525 Clipboard::ObjectMapParams params
;
526 params
.push_back(placeholder_param
);
527 params
.push_back(size_param
);
529 Clipboard::ObjectMap objects
;
530 objects
[Clipboard::CBF_SMBITMAP
] = params
;
532 WriteObjectsToClipboard(objects
);
533 EXPECT_FALSE(clipboard().IsFormatAvailable(Clipboard::GetBitmapFormatType(),
534 CLIPBOARD_TYPE_COPY_PASTE
));
537 TEST_F(ClipboardTest
, DataTest
) {
538 const ui::Clipboard::FormatType kFormat
=
539 ui::Clipboard::GetFormatType("chromium/x-test-format");
540 std::string
payload("test string");
542 write_pickle
.WriteString(payload
);
545 ScopedClipboardWriter
clipboard_writer(&clipboard(),
546 CLIPBOARD_TYPE_COPY_PASTE
);
547 clipboard_writer
.WritePickledData(write_pickle
, kFormat
);
550 ASSERT_TRUE(clipboard().IsFormatAvailable(
551 kFormat
, CLIPBOARD_TYPE_COPY_PASTE
));
553 clipboard().ReadData(kFormat
, &output
);
554 ASSERT_FALSE(output
.empty());
556 Pickle
read_pickle(output
.data(), output
.size());
557 PickleIterator
iter(read_pickle
);
558 std::string unpickled_string
;
559 ASSERT_TRUE(read_pickle
.ReadString(&iter
, &unpickled_string
));
560 EXPECT_EQ(payload
, unpickled_string
);
563 TEST_F(ClipboardTest
, MultipleDataTest
) {
564 const ui::Clipboard::FormatType kFormat1
=
565 ui::Clipboard::GetFormatType("chromium/x-test-format1");
566 std::string
payload1("test string1");
567 Pickle write_pickle1
;
568 write_pickle1
.WriteString(payload1
);
570 const ui::Clipboard::FormatType kFormat2
=
571 ui::Clipboard::GetFormatType("chromium/x-test-format2");
572 std::string
payload2("test string2");
573 Pickle write_pickle2
;
574 write_pickle2
.WriteString(payload2
);
577 ScopedClipboardWriter
clipboard_writer(&clipboard(),
578 CLIPBOARD_TYPE_COPY_PASTE
);
579 clipboard_writer
.WritePickledData(write_pickle1
, kFormat1
);
580 // overwrite the previous pickle for fun
581 clipboard_writer
.WritePickledData(write_pickle2
, kFormat2
);
584 ASSERT_TRUE(clipboard().IsFormatAvailable(
585 kFormat2
, CLIPBOARD_TYPE_COPY_PASTE
));
589 clipboard().ReadData(kFormat2
, &output2
);
590 ASSERT_FALSE(output2
.empty());
592 Pickle
read_pickle2(output2
.data(), output2
.size());
593 PickleIterator
iter2(read_pickle2
);
594 std::string unpickled_string2
;
595 ASSERT_TRUE(read_pickle2
.ReadString(&iter2
, &unpickled_string2
));
596 EXPECT_EQ(payload2
, unpickled_string2
);
599 ScopedClipboardWriter
clipboard_writer(&clipboard(),
600 CLIPBOARD_TYPE_COPY_PASTE
);
601 clipboard_writer
.WritePickledData(write_pickle2
, kFormat2
);
602 // overwrite the previous pickle for fun
603 clipboard_writer
.WritePickledData(write_pickle1
, kFormat1
);
606 ASSERT_TRUE(clipboard().IsFormatAvailable(
607 kFormat1
, CLIPBOARD_TYPE_COPY_PASTE
));
611 clipboard().ReadData(kFormat1
, &output1
);
612 ASSERT_FALSE(output1
.empty());
614 Pickle
read_pickle1(output1
.data(), output1
.size());
615 PickleIterator
iter1(read_pickle1
);
616 std::string unpickled_string1
;
617 ASSERT_TRUE(read_pickle1
.ReadString(&iter1
, &unpickled_string1
));
618 EXPECT_EQ(payload1
, unpickled_string1
);
621 #if !defined(OS_MACOSX) && !defined(OS_ANDROID)
622 TEST_F(ClipboardTest
, HyperlinkTest
) {
623 const std::string
kTitle("The <Example> Company's \"home page\"");
624 const std::string
kUrl("http://www.example.com?x=3<=3#\"'<>");
625 const std::string
kExpectedHtml(
626 "<a href=\"http://www.example.com?x=3&lt=3#"'<>\">"
627 "The <Example> Company's "home page"</a>");
629 std::string url_result
;
630 base::string16 html_result
;
632 ScopedClipboardWriter
clipboard_writer(&clipboard(),
633 CLIPBOARD_TYPE_COPY_PASTE
);
634 clipboard_writer
.WriteHyperlink(ASCIIToUTF16(kTitle
), kUrl
);
637 EXPECT_TRUE(clipboard().IsFormatAvailable(Clipboard::GetHtmlFormatType(),
638 CLIPBOARD_TYPE_COPY_PASTE
));
640 clipboard().ReadHTML(CLIPBOARD_TYPE_COPY_PASTE
, &html_result
, &url_result
,
642 EXPECT_PRED2(MarkupMatches
, ASCIIToUTF16(kExpectedHtml
), html_result
);
646 #if defined(OS_WIN) // Windows only tests.
647 TEST_F(ClipboardTest
, WebSmartPasteTest
) {
649 ScopedClipboardWriter
clipboard_writer(&clipboard(),
650 CLIPBOARD_TYPE_COPY_PASTE
);
651 clipboard_writer
.WriteWebSmartPaste();
654 EXPECT_TRUE(clipboard().IsFormatAvailable(
655 Clipboard::GetWebKitSmartPasteFormatType(), CLIPBOARD_TYPE_COPY_PASTE
));
658 void HtmlTestHelper(const std::string
& cf_html
,
659 const std::string
& expected_html
) {
661 ClipboardUtil::CFHtmlToHtml(cf_html
, &html
, NULL
);
662 EXPECT_EQ(html
, expected_html
);
665 TEST_F(ClipboardTest
, HtmlTest
) {
666 // Test converting from CF_HTML format data with <!--StartFragment--> and
667 // <!--EndFragment--> comments, like from MS Word.
668 HtmlTestHelper("Version:1.0\r\n"
669 "StartHTML:0000000105\r\n"
670 "EndHTML:0000000199\r\n"
671 "StartFragment:0000000123\r\n"
672 "EndFragment:0000000161\r\n"
676 "<!--StartFragment-->\r\n"
680 "<!--EndFragment-->\r\n"
685 // Test converting from CF_HTML format data without <!--StartFragment--> and
686 // <!--EndFragment--> comments, like from OpenOffice Writer.
687 HtmlTestHelper("Version:1.0\r\n"
688 "StartHTML:0000000105\r\n"
689 "EndHTML:0000000151\r\n"
690 "StartFragment:0000000121\r\n"
691 "EndFragment:0000000131\r\n"
699 #endif // defined(OS_WIN)
701 // Test writing all formats we have simultaneously.
702 TEST_F(ClipboardTest
, WriteEverything
) {
704 ScopedClipboardWriter
writer(&clipboard(), CLIPBOARD_TYPE_COPY_PASTE
);
705 writer
.WriteText(UTF8ToUTF16("foo"));
706 writer
.WriteURL(UTF8ToUTF16("foo"));
707 writer
.WriteHTML(UTF8ToUTF16("foo"), "bar");
708 writer
.WriteBookmark(UTF8ToUTF16("foo"), "bar");
709 writer
.WriteHyperlink(ASCIIToUTF16("foo"), "bar");
710 writer
.WriteWebSmartPaste();
711 // Left out: WriteFile, WriteFiles, WriteBitmapFromPixels, WritePickledData.
714 // Passes if we don't crash.
717 // TODO(dcheng): Fix this test for Android. It's rather involved, since the
718 // clipboard change listener is posted to the Java message loop, and spinning
719 // that loop from C++ to trigger the callback in the test requires a non-trivial
720 // amount of additional work.
721 #if !defined(OS_ANDROID)
722 // Simple test that the sequence number appears to change when the clipboard is
724 // TODO(dcheng): Add a version to test CLIPBOARD_TYPE_SELECTION.
725 TEST_F(ClipboardTest
, GetSequenceNumber
) {
726 const uint64 first_sequence_number
=
727 clipboard().GetSequenceNumber(CLIPBOARD_TYPE_COPY_PASTE
);
730 ScopedClipboardWriter
writer(&clipboard(), CLIPBOARD_TYPE_COPY_PASTE
);
731 writer
.WriteText(UTF8ToUTF16("World"));
734 // On some platforms, the sequence number is updated by a UI callback so pump
735 // the message loop to make sure we get the notification.
736 base::RunLoop().RunUntilIdle();
738 const uint64 second_sequence_number
=
739 clipboard().GetSequenceNumber(CLIPBOARD_TYPE_COPY_PASTE
);
741 EXPECT_NE(first_sequence_number
, second_sequence_number
);
745 #if defined(OS_ANDROID)
747 // Test that if another application writes some text to the pasteboard the
748 // clipboard properly invalidates other types.
749 TEST_F(ClipboardTest
, InternalClipboardInvalidation
) {
750 // Write a Webkit smart paste tag to our clipboard.
752 ScopedClipboardWriter
clipboard_writer(&clipboard(),
753 CLIPBOARD_TYPE_COPY_PASTE
);
754 clipboard_writer
.WriteWebSmartPaste();
756 EXPECT_TRUE(clipboard().IsFormatAvailable(
757 Clipboard::GetWebKitSmartPasteFormatType(), CLIPBOARD_TYPE_COPY_PASTE
));
760 // Simulate that another application copied something in the Clipboard
762 std::string
new_value("Some text copied by some other app");
763 using base::android::ConvertUTF8ToJavaString
;
764 using base::android::MethodID
;
765 using base::android::ScopedJavaLocalRef
;
767 JNIEnv
* env
= base::android::AttachCurrentThread();
770 jobject context
= base::android::GetApplicationContext();
771 ASSERT_TRUE(context
);
773 ScopedJavaLocalRef
<jclass
> context_class
=
774 base::android::GetClass(env
, "android/content/Context");
776 jmethodID get_system_service
= MethodID::Get
<MethodID::TYPE_INSTANCE
>(
777 env
, context_class
.obj(), "getSystemService",
778 "(Ljava/lang/String;)Ljava/lang/Object;");
780 // Retrieve the system service.
781 ScopedJavaLocalRef
<jstring
> service_name
= ConvertUTF8ToJavaString(
783 ScopedJavaLocalRef
<jobject
> clipboard_manager(
784 env
, env
->CallObjectMethod(
785 context
, get_system_service
, service_name
.obj()));
786 ASSERT_TRUE(clipboard_manager
.obj() && !base::android::ClearException(env
));
788 ScopedJavaLocalRef
<jclass
> clipboard_class
=
789 base::android::GetClass(env
, "android/text/ClipboardManager");
790 jmethodID set_text
= MethodID::Get
<MethodID::TYPE_INSTANCE
>(
791 env
, clipboard_class
.obj(), "setText", "(Ljava/lang/CharSequence;)V");
792 ScopedJavaLocalRef
<jstring
> new_value_string
= ConvertUTF8ToJavaString(
793 env
, new_value
.c_str());
795 // Will need to call toString as CharSequence is not always a String.
796 env
->CallVoidMethod(clipboard_manager
.obj(),
798 new_value_string
.obj());
800 // The WebKit smart paste tag should now be gone.
801 EXPECT_FALSE(clipboard().IsFormatAvailable(
802 Clipboard::GetWebKitSmartPasteFormatType(), CLIPBOARD_TYPE_COPY_PASTE
));
804 // Make sure some text is available
805 EXPECT_TRUE(clipboard().IsFormatAvailable(
806 Clipboard::GetPlainTextWFormatType(), CLIPBOARD_TYPE_COPY_PASTE
));
808 // Make sure the text is what we inserted while simulating the other app
809 std::string contents
;
810 clipboard().ReadAsciiText(CLIPBOARD_TYPE_COPY_PASTE
, &contents
);
811 EXPECT_EQ(contents
, new_value
);