Parameterize ui::Clipboard tests.
[chromium-blink-merge.git] / ui / base / clipboard / clipboard_unittest.cc
blobb2bb63c81bee41097ff2dd77a4590b03f6153d0f
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"
7 #include <string>
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"
26 #if defined(OS_WIN)
27 #include "ui/base/clipboard/clipboard_util_win.h"
28 #endif
30 #if defined(OS_ANDROID)
31 #include "base/android/jni_android.h"
32 #include "base/android/jni_string.h"
33 #endif
35 #if defined(USE_AURA)
36 #include "ui/events/platform/platform_event_source.h"
37 #endif
39 using base::ASCIIToUTF16;
40 using base::UTF8ToUTF16;
41 using base::UTF16ToUTF8;
43 namespace ui {
45 template <typename ClipboardTraits>
46 class ClipboardTest : public PlatformTest {
47 public:
48 #if defined(USE_AURA)
49 ClipboardTest()
50 : event_source_(PlatformEventSource::CreateDefault()),
51 clipboard_(ClipboardTraits::Create()) {}
52 #else
53 ClipboardTest() : clipboard_(ClipboardTraits::Create()) {}
54 #endif
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);
63 protected:
64 Clipboard& clipboard() { return *clipboard_; }
66 void WriteObjectsToClipboard(const Clipboard::ObjectMap& objects) {
67 WriteObjectsToClipboard(&clipboard(), objects);
70 private:
71 base::MessageLoopForUI message_loop_;
72 #if defined(USE_AURA)
73 scoped_ptr<PlatformEventSource> event_source_;
74 #endif
75 // ui::Clipboard has a protected destructor, so scoped_ptr doesn't work here.
76 Clipboard* const clipboard_;
79 namespace {
81 bool MarkupMatches(const base::string16& expected_markup,
82 const base::string16& actual_markup) {
83 return actual_markup.find(expected_markup) != base::string16::npos;
86 } // namespace
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));
148 uint32 ignored;
149 this->clipboard().ReadHTML(CLIPBOARD_TYPE_COPY_PASTE, &markup_result,
150 &url_result, &ignored, &ignored);
151 EXPECT_PRED2(MarkupMatches, markup, markup_result);
152 #if defined(OS_WIN)
153 // TODO(playmobil): It's not clear that non windows clipboards need to support
154 // this.
155 EXPECT_EQ(url, url_result);
156 #endif // defined(OS_WIN)
159 TYPED_TEST(ClipboardTest, RTFTest) {
160 std::string rtf =
161 "{\\rtf1\\ansi{\\fonttbl\\f0\\fswiss Helvetica;}\\f0\\pard\n"
162 "This is some {\\b bold} text.\\par\n"
163 "}";
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));
172 std::string result;
173 this->clipboard().ReadRTF(CLIPBOARD_TYPE_COPY_PASTE, &result);
174 EXPECT_EQ(rtf, result);
177 // TODO(dnicoara) Enable test once Ozone implements clipboard support:
178 // crbug.com/361707
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);
208 uint32 ignored;
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);
214 #endif
216 TYPED_TEST(ClipboardTest, TrickyHTMLTest) {
217 base::string16 markup(ASCIIToUTF16("<em>Bye!<!--EndFragment --></em>")),
218 markup_result;
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));
230 uint32 ignored;
231 this->clipboard().ReadHTML(CLIPBOARD_TYPE_COPY_PASTE, &markup_result,
232 &url_result, &ignored, &ignored);
233 EXPECT_PRED2(MarkupMatches, markup, markup_result);
234 #if defined(OS_WIN)
235 // TODO(playmobil): It's not clear that non windows clipboards need to support
236 // this.
237 EXPECT_EQ(url, url_result);
238 #endif // defined(OS_WIN)
241 #if defined(OS_WIN)
242 TYPED_TEST(ClipboardTest, UniodeHTMLTest) {
243 base::string16 markup(UTF8ToUTF16("<div>A \xc3\xb8 \xe6\xb0\xb4</div>")),
244 markup_result;
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;
255 uint32 fragment_end;
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));
303 uint32 ignored;
304 this->clipboard().ReadHTML(CLIPBOARD_TYPE_COPY_PASTE, &markup_result,
305 &url_result, &ignored, &ignored);
306 EXPECT_PRED2(MarkupMatches, markup, markup_result);
307 #if defined(OS_WIN)
308 // TODO(playmobil): It's not clear that non windows clipboards need to support
309 // this.
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)
340 ascii_text.clear();
341 this->clipboard().ReadAsciiText(CLIPBOARD_TYPE_SELECTION, &ascii_text);
342 EXPECT_EQ(UTF16ToUTF8(url), ascii_text);
343 #endif
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;
368 #if defined(OS_WIN)
369 current_process = GetCurrentProcess();
370 #endif
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,
393 objects);
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),
420 gfx::Size(4, 3));
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),
435 gfx::Size(2, 7));
439 namespace {
440 // A size class that just happens to have the same layout as gfx::Size!
441 struct UnsafeSize {
442 int width;
443 int height;
445 COMPILE_ASSERT(sizeof(UnsafeSize) == sizeof(gfx::Size),
446 UnsafeSize_must_be_same_size_as_gfx_Size);
447 } // namespace
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
503 // representation.
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");
548 Pickle write_pickle;
549 write_pickle.WriteString(payload);
552 ScopedClipboardWriter clipboard_writer(CLIPBOARD_TYPE_COPY_PASTE);
553 clipboard_writer.WritePickledData(write_pickle, kFormat);
556 ASSERT_TRUE(
557 this->clipboard().IsFormatAvailable(kFormat, CLIPBOARD_TYPE_COPY_PASTE));
558 std::string output;
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);
589 ASSERT_TRUE(
590 this->clipboard().IsFormatAvailable(kFormat2, CLIPBOARD_TYPE_COPY_PASTE));
592 // Check string 2.
593 std::string output2;
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);
610 ASSERT_TRUE(
611 this->clipboard().IsFormatAvailable(kFormat1, CLIPBOARD_TYPE_COPY_PASTE));
613 // Check string 1.
614 std::string output1;
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&lt=3#\"'<>");
629 const std::string kExpectedHtml(
630 "<a href=\"http://www.example.com?x=3&amp;lt=3#&quot;&#39;&lt;&gt;\">"
631 "The &lt;Example&gt; Company&#39;s &quot;home page&quot;</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));
642 uint32 ignored;
643 this->clipboard().ReadHTML(CLIPBOARD_TYPE_COPY_PASTE, &html_result,
644 &url_result, &ignored, &ignored);
645 EXPECT_PRED2(MarkupMatches, ASCIIToUTF16(kExpectedHtml), html_result);
647 #endif
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) {
662 std::string 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"
675 "\r\n"
676 "<html>\r\n"
677 "<body>\r\n"
678 "<!--StartFragment-->\r\n"
679 "\r\n"
680 "<p>Foo</p>\r\n"
681 "\r\n"
682 "<!--EndFragment-->\r\n"
683 "</body>\r\n"
684 "</html>\r\n\r\n",
685 "<p>Foo</p>");
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"
694 "<html>\r\n"
695 "<body>\r\n"
696 "<p>Foo</p>\r\n"
697 "</body>\r\n"
698 "</html>\r\n\r\n",
699 "<p>Foo</p>");
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
725 // written to.
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);
745 #endif
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();
769 ASSERT_TRUE(env);
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(
783 env, "clipboard");
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(),
798 set_text,
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);
814 #endif
816 } // namespace ui