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. 4 5#include "build/build_config.h" 6 7#include <string> 8 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/strings/string_util.h" 14#include "base/strings/utf_string_conversions.h" 15#include "testing/gtest/include/gtest/gtest.h" 16#include "testing/platform_test.h" 17#include "third_party/skia/include/core/SkBitmap.h" 18#include "third_party/skia/include/core/SkColor.h" 19#include "third_party/skia/include/core/SkScalar.h" 20#include "third_party/skia/include/core/SkUnPreMultiply.h" 21#include "ui/base/clipboard/clipboard.h" 22#include "ui/base/clipboard/scoped_clipboard_writer.h" 23#include "ui/gfx/size.h" 24 25#if defined(OS_WIN) 26#include "ui/base/clipboard/clipboard_util_win.h" 27#endif 28 29#if defined(OS_ANDROID) 30#include "base/android/jni_android.h" 31#include "base/android/jni_string.h" 32#endif 33 34namespace ui { 35 36class ClipboardTest : public PlatformTest { 37 protected: 38 Clipboard& clipboard() { return clipboard_; } 39 40 private: 41 base::MessageLoopForUI message_loop_; 42 Clipboard clipboard_; 43}; 44 45namespace { 46 47bool MarkupMatches(const string16& expected_markup, 48 const string16& actual_markup) { 49 return actual_markup.find(expected_markup) != string16::npos; 50} 51 52} // namespace 53 54TEST_F(ClipboardTest, ClearTest) { 55 { 56 ScopedClipboardWriter clipboard_writer(&clipboard(), 57 CLIPBOARD_TYPE_COPY_PASTE); 58 clipboard_writer.WriteText(ASCIIToUTF16("clear me")); 59 } 60 61 clipboard().Clear(CLIPBOARD_TYPE_COPY_PASTE); 62 63 EXPECT_FALSE(clipboard().IsFormatAvailable( 64 Clipboard::GetPlainTextWFormatType(), CLIPBOARD_TYPE_COPY_PASTE)); 65 EXPECT_FALSE(clipboard().IsFormatAvailable( 66 Clipboard::GetPlainTextFormatType(), CLIPBOARD_TYPE_COPY_PASTE)); 67} 68 69TEST_F(ClipboardTest, TextTest) { 70 string16 text(ASCIIToUTF16("This is a string16!#$")), text_result; 71 std::string ascii_text; 72 73 { 74 ScopedClipboardWriter clipboard_writer(&clipboard(), 75 CLIPBOARD_TYPE_COPY_PASTE); 76 clipboard_writer.WriteText(text); 77 } 78 79 EXPECT_TRUE(clipboard().IsFormatAvailable( 80 Clipboard::GetPlainTextWFormatType(), CLIPBOARD_TYPE_COPY_PASTE)); 81 EXPECT_TRUE(clipboard().IsFormatAvailable(Clipboard::GetPlainTextFormatType(), 82 CLIPBOARD_TYPE_COPY_PASTE)); 83 clipboard().ReadText(CLIPBOARD_TYPE_COPY_PASTE, &text_result); 84 85 EXPECT_EQ(text, text_result); 86 clipboard().ReadAsciiText(CLIPBOARD_TYPE_COPY_PASTE, &ascii_text); 87 EXPECT_EQ(UTF16ToUTF8(text), ascii_text); 88} 89 90TEST_F(ClipboardTest, HTMLTest) { 91 string16 markup(ASCIIToUTF16("<string>Hi!</string>")), markup_result; 92 string16 plain(ASCIIToUTF16("Hi!")), plain_result; 93 std::string url("http://www.example.com/"), url_result; 94 95 { 96 ScopedClipboardWriter clipboard_writer(&clipboard(), 97 CLIPBOARD_TYPE_COPY_PASTE); 98 clipboard_writer.WriteText(plain); 99 clipboard_writer.WriteHTML(markup, url); 100 } 101 102 EXPECT_TRUE(clipboard().IsFormatAvailable(Clipboard::GetHtmlFormatType(), 103 CLIPBOARD_TYPE_COPY_PASTE)); 104 uint32 ignored; 105 clipboard().ReadHTML(CLIPBOARD_TYPE_COPY_PASTE, &markup_result, &url_result, 106 &ignored, &ignored); 107 EXPECT_PRED2(MarkupMatches, markup, markup_result); 108#if defined(OS_WIN) 109 // TODO(playmobil): It's not clear that non windows clipboards need to support 110 // this. 111 EXPECT_EQ(url, url_result); 112#endif // defined(OS_WIN) 113} 114 115TEST_F(ClipboardTest, RTFTest) { 116 std::string rtf = 117 "{\\rtf1\\ansi{\\fonttbl\\f0\\fswiss Helvetica;}\\f0\\pard\n" 118 "This is some {\\b bold} text.\\par\n" 119 "}"; 120 121 { 122 ScopedClipboardWriter clipboard_writer(&clipboard(), 123 CLIPBOARD_TYPE_COPY_PASTE); 124 clipboard_writer.WriteRTF(rtf); 125 } 126 127 EXPECT_TRUE(clipboard().IsFormatAvailable(Clipboard::GetRtfFormatType(), 128 CLIPBOARD_TYPE_COPY_PASTE)); 129 std::string result; 130 clipboard().ReadRTF(CLIPBOARD_TYPE_COPY_PASTE, &result); 131 EXPECT_EQ(rtf, result); 132} 133 134#if defined(TOOLKIT_GTK) 135TEST_F(ClipboardTest, MultipleBufferTest) { 136 string16 text(ASCIIToUTF16("Standard")), text_result; 137 string16 markup(ASCIIToUTF16("<string>Selection</string>")), markup_result; 138 std::string url("http://www.example.com/"), url_result; 139 140 { 141 ScopedClipboardWriter clipboard_writer(&clipboard(), 142 CLIPBOARD_TYPE_COPY_PASTE); 143 clipboard_writer.WriteText(text); 144 } 145 146 { 147 ScopedClipboardWriter clipboard_writer(&clipboard(), 148 CLIPBOARD_TYPE_SELECTION); 149 clipboard_writer.WriteHTML(markup, url); 150 } 151 152 EXPECT_TRUE(clipboard().IsFormatAvailable(Clipboard::GetPlainTextFormatType(), 153 CLIPBOARD_TYPE_COPY_PASTE)); 154 EXPECT_FALSE(clipboard().IsFormatAvailable( 155 Clipboard::GetPlainTextFormatType(), 156 CLIPBOARD_TYPE_SELECTION)); 157 158 EXPECT_FALSE(clipboard().IsFormatAvailable(Clipboard::GetHtmlFormatType(), 159 CLIPBOARD_TYPE_COPY_PASTE)); 160 EXPECT_TRUE(clipboard().IsFormatAvailable(Clipboard::GetHtmlFormatType(), 161 CLIPBOARD_TYPE_SELECTION)); 162 163 clipboard().ReadText(CLIPBOARD_TYPE_COPY_PASTE, &text_result); 164 EXPECT_EQ(text, text_result); 165 166 uint32 ignored; 167 clipboard().ReadHTML(CLIPBOARD_TYPE_SELECTION, 168 &markup_result, 169 &url_result, 170 &ignored, 171 &ignored); 172 EXPECT_PRED2(MarkupMatches, markup, markup_result); 173} 174#endif 175 176TEST_F(ClipboardTest, TrickyHTMLTest) { 177 string16 markup(ASCIIToUTF16("<em>Bye!<!--EndFragment --></em>")), 178 markup_result; 179 std::string url, url_result; 180 string16 plain(ASCIIToUTF16("Bye!")), plain_result; 181 182 { 183 ScopedClipboardWriter clipboard_writer(&clipboard(), 184 CLIPBOARD_TYPE_COPY_PASTE); 185 clipboard_writer.WriteText(plain); 186 clipboard_writer.WriteHTML(markup, url); 187 } 188 189 EXPECT_TRUE(clipboard().IsFormatAvailable(Clipboard::GetHtmlFormatType(), 190 CLIPBOARD_TYPE_COPY_PASTE)); 191 uint32 ignored; 192 clipboard().ReadHTML(CLIPBOARD_TYPE_COPY_PASTE, &markup_result, &url_result, 193 &ignored, &ignored); 194 EXPECT_PRED2(MarkupMatches, markup, markup_result); 195#if defined(OS_WIN) 196 // TODO(playmobil): It's not clear that non windows clipboards need to support 197 // this. 198 EXPECT_EQ(url, url_result); 199#endif // defined(OS_WIN) 200} 201 202#if defined(OS_WIN) 203TEST_F(ClipboardTest, UniodeHTMLTest) { 204 string16 markup(UTF8ToUTF16("<div>A \xc3\xb8 \xe6\xb0\xb4</div>")), 205 markup_result; 206 std::string url, url_result; 207 208 { 209 ScopedClipboardWriter clipboard_writer(&clipboard(), 210 CLIPBOARD_TYPE_COPY_PASTE); 211 clipboard_writer.WriteHTML(markup, url); 212 } 213 214 EXPECT_TRUE(clipboard().IsFormatAvailable(Clipboard::GetHtmlFormatType(), 215 CLIPBOARD_TYPE_COPY_PASTE)); 216 uint32 fragment_start; 217 uint32 fragment_end; 218 clipboard().ReadHTML(CLIPBOARD_TYPE_COPY_PASTE, &markup_result, &url_result, 219 &fragment_start, &fragment_end); 220 EXPECT_PRED2(MarkupMatches, markup, markup_result); 221 EXPECT_EQ(url, url_result); 222 // Make sure that fragment indices were adjusted when converting. 223 EXPECT_EQ(36, fragment_start); 224 EXPECT_EQ(52, fragment_end); 225} 226#endif // defined(OS_WIN) 227 228#if defined(TOOLKIT_GTK) 229// Regression test for crbug.com/56298 (pasting empty HTML crashes Linux). 230TEST_F(ClipboardTest, EmptyHTMLTest) { 231 // ScopedClipboardWriter doesn't let us write empty data to the clipboard. 232 clipboard().clipboard_data_ = new Clipboard::TargetMap(); 233 // The 1 is so the compiler doesn't warn about allocating an empty array. 234 char* empty = new char[1]; 235 clipboard().InsertMapping("text/html", empty, 0U); 236 clipboard().SetGtkClipboard(CLIPBOARD_TYPE_COPY_PASTE); 237 238 EXPECT_TRUE(clipboard().IsFormatAvailable(Clipboard::GetHtmlFormatType(), 239 CLIPBOARD_TYPE_COPY_PASTE)); 240 string16 markup_result; 241 std::string url_result; 242 uint32 ignored; 243 clipboard().ReadHTML(CLIPBOARD_TYPE_COPY_PASTE, &markup_result, &url_result, 244 &ignored, &ignored); 245 EXPECT_PRED2(MarkupMatches, string16(), markup_result); 246} 247#endif 248 249// TODO(estade): Port the following test (decide what target we use for urls) 250#if !defined(OS_POSIX) || defined(OS_MACOSX) 251TEST_F(ClipboardTest, BookmarkTest) { 252 string16 title(ASCIIToUTF16("The Example Company")), title_result; 253 std::string url("http://www.example.com/"), url_result; 254 255 { 256 ScopedClipboardWriter clipboard_writer(&clipboard(), 257 CLIPBOARD_TYPE_COPY_PASTE); 258 clipboard_writer.WriteBookmark(title, url); 259 } 260 261 EXPECT_TRUE(clipboard().IsFormatAvailable(Clipboard::GetUrlWFormatType(), 262 CLIPBOARD_TYPE_COPY_PASTE)); 263 clipboard().ReadBookmark(&title_result, &url_result); 264 EXPECT_EQ(title, title_result); 265 EXPECT_EQ(url, url_result); 266} 267#endif // defined(OS_WIN) 268 269TEST_F(ClipboardTest, MultiFormatTest) { 270 string16 text(ASCIIToUTF16("Hi!")), text_result; 271 string16 markup(ASCIIToUTF16("<strong>Hi!</string>")), markup_result; 272 std::string url("http://www.example.com/"), url_result; 273 std::string ascii_text; 274 275 { 276 ScopedClipboardWriter clipboard_writer(&clipboard(), 277 CLIPBOARD_TYPE_COPY_PASTE); 278 clipboard_writer.WriteHTML(markup, url); 279 clipboard_writer.WriteText(text); 280 } 281 282 EXPECT_TRUE(clipboard().IsFormatAvailable(Clipboard::GetHtmlFormatType(), 283 CLIPBOARD_TYPE_COPY_PASTE)); 284 EXPECT_TRUE(clipboard().IsFormatAvailable( 285 Clipboard::GetPlainTextWFormatType(), CLIPBOARD_TYPE_COPY_PASTE)); 286 EXPECT_TRUE(clipboard().IsFormatAvailable( 287 Clipboard::GetPlainTextFormatType(), CLIPBOARD_TYPE_COPY_PASTE)); 288 uint32 ignored; 289 clipboard().ReadHTML(CLIPBOARD_TYPE_COPY_PASTE, &markup_result, &url_result, 290 &ignored, &ignored); 291 EXPECT_PRED2(MarkupMatches, markup, markup_result); 292#if defined(OS_WIN) 293 // TODO(playmobil): It's not clear that non windows clipboards need to support 294 // this. 295 EXPECT_EQ(url, url_result); 296#endif // defined(OS_WIN) 297 clipboard().ReadText(CLIPBOARD_TYPE_COPY_PASTE, &text_result); 298 EXPECT_EQ(text, text_result); 299 clipboard().ReadAsciiText(CLIPBOARD_TYPE_COPY_PASTE, &ascii_text); 300 EXPECT_EQ(UTF16ToUTF8(text), ascii_text); 301} 302 303TEST_F(ClipboardTest, URLTest) { 304 string16 url(ASCIIToUTF16("http://www.google.com/")); 305 306 { 307 ScopedClipboardWriter clipboard_writer(&clipboard(), 308 CLIPBOARD_TYPE_COPY_PASTE); 309 clipboard_writer.WriteURL(url); 310 } 311 312 EXPECT_TRUE(clipboard().IsFormatAvailable( 313 Clipboard::GetPlainTextWFormatType(), CLIPBOARD_TYPE_COPY_PASTE)); 314 EXPECT_TRUE(clipboard().IsFormatAvailable(Clipboard::GetPlainTextFormatType(), 315 CLIPBOARD_TYPE_COPY_PASTE)); 316 string16 text_result; 317 clipboard().ReadText(CLIPBOARD_TYPE_COPY_PASTE, &text_result); 318 319 EXPECT_EQ(text_result, url); 320 321 std::string ascii_text; 322 clipboard().ReadAsciiText(CLIPBOARD_TYPE_COPY_PASTE, &ascii_text); 323 EXPECT_EQ(UTF16ToUTF8(url), ascii_text); 324 325#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) 326 ascii_text.clear(); 327 clipboard().ReadAsciiText(CLIPBOARD_TYPE_SELECTION, &ascii_text); 328 EXPECT_EQ(UTF16ToUTF8(url), ascii_text); 329#endif 330} 331 332// Note that |bitmap_data| is not premultiplied! 333static void TestBitmapWrite(Clipboard* clipboard, 334 const uint32* bitmap_data, 335 size_t bitmap_data_size, 336 const gfx::Size& size) { 337 // Create shared memory region. 338 base::SharedMemory shared_buf; 339 ASSERT_TRUE(shared_buf.CreateAndMapAnonymous(bitmap_data_size)); 340 memcpy(shared_buf.memory(), bitmap_data, bitmap_data_size); 341 // CBF_SMBITMAP expects premultiplied bitmap data so do that now. 342 uint32* pixel_buffer = static_cast<uint32*>(shared_buf.memory()); 343 for (int j = 0; j < size.height(); ++j) { 344 for (int i = 0; i < size.width(); ++i) { 345 uint32& pixel = pixel_buffer[i + j * size.width()]; 346 pixel = SkPreMultiplyColor(pixel); 347 } 348 } 349 base::SharedMemoryHandle handle_to_share; 350 base::ProcessHandle current_process = base::kNullProcessHandle; 351#if defined(OS_WIN) 352 current_process = GetCurrentProcess(); 353#endif 354 shared_buf.ShareToProcess(current_process, &handle_to_share); 355 ASSERT_TRUE(shared_buf.Unmap()); 356 357 // Setup data for clipboard(). 358 Clipboard::ObjectMapParam placeholder_param; 359 Clipboard::ObjectMapParam size_param; 360 const char* size_data = reinterpret_cast<const char*>(&size); 361 for (size_t i = 0; i < sizeof(size); ++i) 362 size_param.push_back(size_data[i]); 363 364 Clipboard::ObjectMapParams params; 365 params.push_back(placeholder_param); 366 params.push_back(size_param); 367 368 Clipboard::ObjectMap objects; 369 objects[Clipboard::CBF_SMBITMAP] = params; 370 ASSERT_TRUE(Clipboard::ReplaceSharedMemHandle( 371 &objects, handle_to_share, current_process)); 372 373 clipboard->WriteObjects(CLIPBOARD_TYPE_COPY_PASTE, objects); 374 375 EXPECT_TRUE(clipboard->IsFormatAvailable(Clipboard::GetBitmapFormatType(), 376 CLIPBOARD_TYPE_COPY_PASTE)); 377 const SkBitmap& image = clipboard->ReadImage(CLIPBOARD_TYPE_COPY_PASTE); 378 EXPECT_EQ(size, gfx::Size(image.width(), image.height())); 379 SkAutoLockPixels image_lock(image); 380 for (int j = 0; j < image.height(); ++j) { 381 const uint32* row_address = image.getAddr32(0, j); 382 for (int i = 0; i < image.width(); ++i) { 383 int offset = i + j * image.width(); 384 uint32 pixel = SkPreMultiplyColor(bitmap_data[offset]); 385#if defined(TOOLKIT_GTK) 386 // Non-Aura GTK doesn't support alpha transparency. Instead, the alpha 387 // channel is always set to 0xFF - see http://crbug.com/154573. 388 // However, since we premultiplied above, we must also premultiply here 389 // before unpremultiplying and setting alpha to 0xFF; otherwise, the 390 // results will not match GTK's. 391 EXPECT_EQ( 392 SkUnPreMultiply::PMColorToColor(pixel) | 0xFF000000, row_address[i]) 393 << "i = " << i << ", j = " << j; 394#else 395 EXPECT_EQ(pixel, row_address[i]) 396 << "i = " << i << ", j = " << j; 397#endif // defined(TOOLKIT_GTK) 398 } 399 } 400} 401 402TEST_F(ClipboardTest, SharedBitmapTest) { 403 const uint32 fake_bitmap_1[] = { 404 0x46155189, 0xF6A55C8D, 0x79845674, 0xFA57BD89, 405 0x78FD46AE, 0x87C64F5A, 0x36EDC5AF, 0x4378F568, 406 0x91E9F63A, 0xC31EA14F, 0x69AB32DF, 0x643A3FD1, 407 }; 408 { 409 SCOPED_TRACE("first bitmap"); 410 TestBitmapWrite( 411 &clipboard(), fake_bitmap_1, sizeof(fake_bitmap_1), gfx::Size(4, 3)); 412 } 413 414 const uint32 fake_bitmap_2[] = { 415 0x46155189, 0xF6A55C8D, 416 0x79845674, 0xFA57BD89, 417 0x78FD46AE, 0x87C64F5A, 418 0x36EDC5AF, 0x4378F568, 419 0x91E9F63A, 0xC31EA14F, 420 0x69AB32DF, 0x643A3FD1, 421 0xA6DF041D, 0x83046278, 422 }; 423 { 424 SCOPED_TRACE("second bitmap"); 425 TestBitmapWrite( 426 &clipboard(), fake_bitmap_2, sizeof(fake_bitmap_2), gfx::Size(2, 7)); 427 } 428} 429 430namespace { 431// A size class that just happens to have the same layout as gfx::Size! 432struct UnsafeSize { 433 int width; 434 int height; 435}; 436COMPILE_ASSERT(sizeof(UnsafeSize) == sizeof(gfx::Size), 437 UnsafeSize_must_be_same_size_as_gfx_Size); 438} // namespace 439 440TEST_F(ClipboardTest, SharedBitmapWithTwoNegativeSizes) { 441 Clipboard::ObjectMapParam placeholder_param; 442 void* crash_me = reinterpret_cast<void*>(57); 443 placeholder_param.resize(sizeof(crash_me)); 444 memcpy(&placeholder_param.front(), &crash_me, sizeof(crash_me)); 445 446 Clipboard::ObjectMapParam size_param; 447 UnsafeSize size = {-100, -100}; 448 size_param.resize(sizeof(size)); 449 memcpy(&size_param.front(), &size, sizeof(size)); 450 451 Clipboard::ObjectMapParams params; 452 params.push_back(placeholder_param); 453 params.push_back(size_param); 454 455 Clipboard::ObjectMap objects; 456 objects[Clipboard::CBF_SMBITMAP] = params; 457 458 clipboard().WriteObjects(CLIPBOARD_TYPE_COPY_PASTE, objects); 459 EXPECT_FALSE(clipboard().IsFormatAvailable(Clipboard::GetBitmapFormatType(), 460 CLIPBOARD_TYPE_COPY_PASTE)); 461} 462 463TEST_F(ClipboardTest, SharedBitmapWithOneNegativeSize) { 464 Clipboard::ObjectMapParam placeholder_param; 465 void* crash_me = reinterpret_cast<void*>(57); 466 placeholder_param.resize(sizeof(crash_me)); 467 memcpy(&placeholder_param.front(), &crash_me, sizeof(crash_me)); 468 469 Clipboard::ObjectMapParam size_param; 470 UnsafeSize size = {-100, 100}; 471 size_param.resize(sizeof(size)); 472 memcpy(&size_param.front(), &size, sizeof(size)); 473 474 Clipboard::ObjectMapParams params; 475 params.push_back(placeholder_param); 476 params.push_back(size_param); 477 478 Clipboard::ObjectMap objects; 479 objects[Clipboard::CBF_SMBITMAP] = params; 480 481 clipboard().WriteObjects(CLIPBOARD_TYPE_COPY_PASTE, objects); 482 EXPECT_FALSE(clipboard().IsFormatAvailable(Clipboard::GetBitmapFormatType(), 483 CLIPBOARD_TYPE_COPY_PASTE)); 484} 485 486TEST_F(ClipboardTest, BitmapWithSuperSize) { 487 Clipboard::ObjectMapParam placeholder_param; 488 void* crash_me = reinterpret_cast<void*>(57); 489 placeholder_param.resize(sizeof(crash_me)); 490 memcpy(&placeholder_param.front(), &crash_me, sizeof(crash_me)); 491 492 Clipboard::ObjectMapParam size_param; 493 // Width just big enough that bytes per row won't fit in a 32-bit 494 // representation. 495 gfx::Size size(0x20000000, 1); 496 size_param.resize(sizeof(size)); 497 memcpy(&size_param.front(), &size, sizeof(size)); 498 499 Clipboard::ObjectMapParams params; 500 params.push_back(placeholder_param); 501 params.push_back(size_param); 502 503 Clipboard::ObjectMap objects; 504 objects[Clipboard::CBF_SMBITMAP] = params; 505 506 clipboard().WriteObjects(CLIPBOARD_TYPE_COPY_PASTE, objects); 507 EXPECT_FALSE(clipboard().IsFormatAvailable(Clipboard::GetBitmapFormatType(), 508 CLIPBOARD_TYPE_COPY_PASTE)); 509} 510 511TEST_F(ClipboardTest, BitmapWithSuperSize2) { 512 Clipboard::ObjectMapParam placeholder_param; 513 void* crash_me = reinterpret_cast<void*>(57); 514 placeholder_param.resize(sizeof(crash_me)); 515 memcpy(&placeholder_param.front(), &crash_me, sizeof(crash_me)); 516 517 Clipboard::ObjectMapParam size_param; 518 // Width and height large enough that SkBitmap::getSize() will be truncated. 519 gfx::Size size(0x0fffffff, 0x0fffffff); 520 size_param.resize(sizeof(size)); 521 memcpy(&size_param.front(), &size, sizeof(size)); 522 523 Clipboard::ObjectMapParams params; 524 params.push_back(placeholder_param); 525 params.push_back(size_param); 526 527 Clipboard::ObjectMap objects; 528 objects[Clipboard::CBF_SMBITMAP] = params; 529 530 clipboard().WriteObjects(CLIPBOARD_TYPE_COPY_PASTE, objects); 531 EXPECT_FALSE(clipboard().IsFormatAvailable(Clipboard::GetBitmapFormatType(), 532 CLIPBOARD_TYPE_COPY_PASTE)); 533} 534 535TEST_F(ClipboardTest, DataTest) { 536 const ui::Clipboard::FormatType kFormat = 537 ui::Clipboard::GetFormatType("chromium/x-test-format"); 538 std::string payload("test string"); 539 Pickle write_pickle; 540 write_pickle.WriteString(payload); 541 542 { 543 ScopedClipboardWriter clipboard_writer(&clipboard(), 544 CLIPBOARD_TYPE_COPY_PASTE); 545 clipboard_writer.WritePickledData(write_pickle, kFormat); 546 } 547 548 ASSERT_TRUE(clipboard().IsFormatAvailable( 549 kFormat, CLIPBOARD_TYPE_COPY_PASTE)); 550 std::string output; 551 clipboard().ReadData(kFormat, &output); 552 ASSERT_FALSE(output.empty()); 553 554 Pickle read_pickle(output.data(), output.size()); 555 PickleIterator iter(read_pickle); 556 std::string unpickled_string; 557 ASSERT_TRUE(read_pickle.ReadString(&iter, &unpickled_string)); 558 EXPECT_EQ(payload, unpickled_string); 559} 560 561TEST_F(ClipboardTest, MultipleDataTest) { 562 const ui::Clipboard::FormatType kFormat1 = 563 ui::Clipboard::GetFormatType("chromium/x-test-format1"); 564 std::string payload1("test string1"); 565 Pickle write_pickle1; 566 write_pickle1.WriteString(payload1); 567 568 const ui::Clipboard::FormatType kFormat2 = 569 ui::Clipboard::GetFormatType("chromium/x-test-format2"); 570 std::string payload2("test string2"); 571 Pickle write_pickle2; 572 write_pickle2.WriteString(payload2); 573 574 { 575 ScopedClipboardWriter clipboard_writer(&clipboard(), 576 CLIPBOARD_TYPE_COPY_PASTE); 577 clipboard_writer.WritePickledData(write_pickle1, kFormat1); 578 // overwrite the previous pickle for fun 579 clipboard_writer.WritePickledData(write_pickle2, kFormat2); 580 } 581 582 ASSERT_TRUE(clipboard().IsFormatAvailable( 583 kFormat2, CLIPBOARD_TYPE_COPY_PASTE)); 584 585 // Check string 2. 586 std::string output2; 587 clipboard().ReadData(kFormat2, &output2); 588 ASSERT_FALSE(output2.empty()); 589 590 Pickle read_pickle2(output2.data(), output2.size()); 591 PickleIterator iter2(read_pickle2); 592 std::string unpickled_string2; 593 ASSERT_TRUE(read_pickle2.ReadString(&iter2, &unpickled_string2)); 594 EXPECT_EQ(payload2, unpickled_string2); 595 596 { 597 ScopedClipboardWriter clipboard_writer(&clipboard(), 598 CLIPBOARD_TYPE_COPY_PASTE); 599 clipboard_writer.WritePickledData(write_pickle2, kFormat2); 600 // overwrite the previous pickle for fun 601 clipboard_writer.WritePickledData(write_pickle1, kFormat1); 602 } 603 604 ASSERT_TRUE(clipboard().IsFormatAvailable( 605 kFormat1, CLIPBOARD_TYPE_COPY_PASTE)); 606 607 // Check string 1. 608 std::string output1; 609 clipboard().ReadData(kFormat1, &output1); 610 ASSERT_FALSE(output1.empty()); 611 612 Pickle read_pickle1(output1.data(), output1.size()); 613 PickleIterator iter1(read_pickle1); 614 std::string unpickled_string1; 615 ASSERT_TRUE(read_pickle1.ReadString(&iter1, &unpickled_string1)); 616 EXPECT_EQ(payload1, unpickled_string1); 617} 618 619#if !defined(OS_MACOSX) && !defined(OS_ANDROID) 620TEST_F(ClipboardTest, HyperlinkTest) { 621 const std::string kTitle("The <Example> Company's \"home page\""); 622 const std::string kUrl("http://www.example.com?x=3<=3#\"'<>"); 623 const std::string kExpectedHtml( 624 "<a href=\"http://www.example.com?x=3<=3#"'<>\">" 625 "The <Example> Company's "home page"</a>"); 626 627 std::string url_result; 628 string16 html_result; 629 { 630 ScopedClipboardWriter clipboard_writer(&clipboard(), 631 CLIPBOARD_TYPE_COPY_PASTE); 632 clipboard_writer.WriteHyperlink(ASCIIToUTF16(kTitle), kUrl); 633 } 634 635 EXPECT_TRUE(clipboard().IsFormatAvailable(Clipboard::GetHtmlFormatType(), 636 CLIPBOARD_TYPE_COPY_PASTE)); 637 uint32 ignored; 638 clipboard().ReadHTML(CLIPBOARD_TYPE_COPY_PASTE, &html_result, &url_result, 639 &ignored, &ignored); 640 EXPECT_PRED2(MarkupMatches, ASCIIToUTF16(kExpectedHtml), html_result); 641} 642#endif 643 644#if defined(OS_WIN) // Windows only tests. 645TEST_F(ClipboardTest, WebSmartPasteTest) { 646 { 647 ScopedClipboardWriter clipboard_writer(&clipboard(), 648 CLIPBOARD_TYPE_COPY_PASTE); 649 clipboard_writer.WriteWebSmartPaste(); 650 } 651 652 EXPECT_TRUE(clipboard().IsFormatAvailable( 653 Clipboard::GetWebKitSmartPasteFormatType(), CLIPBOARD_TYPE_COPY_PASTE)); 654} 655 656void HtmlTestHelper(const std::string& cf_html, 657 const std::string& expected_html) { 658 std::string html; 659 ClipboardUtil::CFHtmlToHtml(cf_html, &html, NULL); 660 EXPECT_EQ(html, expected_html); 661} 662 663TEST_F(ClipboardTest, HtmlTest) { 664 // Test converting from CF_HTML format data with <!--StartFragment--> and 665 // <!--EndFragment--> comments, like from MS Word. 666 HtmlTestHelper("Version:1.0\r\n" 667 "StartHTML:0000000105\r\n" 668 "EndHTML:0000000199\r\n" 669 "StartFragment:0000000123\r\n" 670 "EndFragment:0000000161\r\n" 671 "\r\n" 672 "<html>\r\n" 673 "<body>\r\n" 674 "<!--StartFragment-->\r\n" 675 "\r\n" 676 "<p>Foo</p>\r\n" 677 "\r\n" 678 "<!--EndFragment-->\r\n" 679 "</body>\r\n" 680 "</html>\r\n\r\n", 681 "<p>Foo</p>"); 682 683 // Test converting from CF_HTML format data without <!--StartFragment--> and 684 // <!--EndFragment--> comments, like from OpenOffice Writer. 685 HtmlTestHelper("Version:1.0\r\n" 686 "StartHTML:0000000105\r\n" 687 "EndHTML:0000000151\r\n" 688 "StartFragment:0000000121\r\n" 689 "EndFragment:0000000131\r\n" 690 "<html>\r\n" 691 "<body>\r\n" 692 "<p>Foo</p>\r\n" 693 "</body>\r\n" 694 "</html>\r\n\r\n", 695 "<p>Foo</p>"); 696} 697#endif // defined(OS_WIN) 698 699// Test writing all formats we have simultaneously. 700TEST_F(ClipboardTest, WriteEverything) { 701 { 702 ScopedClipboardWriter writer(&clipboard(), CLIPBOARD_TYPE_COPY_PASTE); 703 writer.WriteText(UTF8ToUTF16("foo")); 704 writer.WriteURL(UTF8ToUTF16("foo")); 705 writer.WriteHTML(UTF8ToUTF16("foo"), "bar"); 706 writer.WriteBookmark(UTF8ToUTF16("foo"), "bar"); 707 writer.WriteHyperlink(ASCIIToUTF16("foo"), "bar"); 708 writer.WriteWebSmartPaste(); 709 // Left out: WriteFile, WriteFiles, WriteBitmapFromPixels, WritePickledData. 710 } 711 712 // Passes if we don't crash. 713} 714 715#if defined(OS_ANDROID) 716 717// Test that if another application writes some text to the pasteboard the 718// clipboard properly invalidates other types. 719TEST_F(ClipboardTest, InternalClipboardInvalidation) { 720 // Write a Webkit smart paste tag to our clipboard. 721 { 722 ScopedClipboardWriter clipboard_writer(&clipboard(), 723 CLIPBOARD_TYPE_COPY_PASTE); 724 clipboard_writer.WriteWebSmartPaste(); 725 } 726 EXPECT_TRUE(clipboard().IsFormatAvailable( 727 Clipboard::GetWebKitSmartPasteFormatType(), CLIPBOARD_TYPE_COPY_PASTE)); 728 729 // 730 // Simulate that another application copied something in the Clipboard 731 // 732 std::string new_value("Some text copied by some other app"); 733 using base::android::ConvertUTF8ToJavaString; 734 using base::android::MethodID; 735 using base::android::ScopedJavaLocalRef; 736 737 JNIEnv* env = base::android::AttachCurrentThread(); 738 ASSERT_TRUE(env); 739 740 jobject context = base::android::GetApplicationContext(); 741 ASSERT_TRUE(context); 742 743 ScopedJavaLocalRef<jclass> context_class = 744 base::android::GetClass(env, "android/content/Context"); 745 746 jmethodID get_system_service = MethodID::Get<MethodID::TYPE_INSTANCE>( 747 env, context_class.obj(), "getSystemService", 748 "(Ljava/lang/String;)Ljava/lang/Object;"); 749 750 // Retrieve the system service. 751 ScopedJavaLocalRef<jstring> service_name = ConvertUTF8ToJavaString( 752 env, "clipboard"); 753 ScopedJavaLocalRef<jobject> clipboard_manager( 754 env, env->CallObjectMethod( 755 context, get_system_service, service_name.obj())); 756 ASSERT_TRUE(clipboard_manager.obj() && !base::android::ClearException(env)); 757 758 ScopedJavaLocalRef<jclass> clipboard_class = 759 base::android::GetClass(env, "android/text/ClipboardManager"); 760 jmethodID set_text = MethodID::Get<MethodID::TYPE_INSTANCE>( 761 env, clipboard_class.obj(), "setText", "(Ljava/lang/CharSequence;)V"); 762 ScopedJavaLocalRef<jstring> new_value_string = ConvertUTF8ToJavaString( 763 env, new_value.c_str()); 764 765 // Will need to call toString as CharSequence is not always a String. 766 env->CallVoidMethod(clipboard_manager.obj(), 767 set_text, 768 new_value_string.obj()); 769 770 // The WebKit smart paste tag should now be gone. 771 EXPECT_FALSE(clipboard().IsFormatAvailable( 772 Clipboard::GetWebKitSmartPasteFormatType(), CLIPBOARD_TYPE_COPY_PASTE)); 773 774 // Make sure some text is available 775 EXPECT_TRUE(clipboard().IsFormatAvailable( 776 Clipboard::GetPlainTextWFormatType(), CLIPBOARD_TYPE_COPY_PASTE)); 777 778 // Make sure the text is what we inserted while simulating the other app 779 std::string contents; 780 clipboard().ReadAsciiText(CLIPBOARD_TYPE_COPY_PASTE, &contents); 781 EXPECT_EQ(contents, new_value); 782} 783#endif 784} // namespace ui 785