Home | History | Annotate | Download | only in clipboard
      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/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"
     25 
     26 #if defined(OS_WIN)
     27 #include "ui/base/clipboard/clipboard_util_win.h"
     28 #endif
     29 
     30 #if defined(OS_ANDROID)
     31 #include "base/android/jni_android.h"
     32 #include "base/android/jni_string.h"
     33 #endif
     34 
     35 #if defined(USE_AURA)
     36 #include "ui/events/platform/platform_event_source.h"
     37 #endif
     38 
     39 using base::ASCIIToUTF16;
     40 using base::UTF8ToUTF16;
     41 using base::UTF16ToUTF8;
     42 
     43 namespace ui {
     44 
     45 class ClipboardTest : public PlatformTest {
     46  public:
     47 #if defined(USE_AURA)
     48   ClipboardTest() : event_source_(ui::PlatformEventSource::CreateDefault()) {}
     49 #else
     50   ClipboardTest() {}
     51 #endif
     52 
     53   static void WriteObjectsToClipboard(ui::Clipboard* clipboard,
     54                                       const Clipboard::ObjectMap& objects) {
     55     clipboard->WriteObjects(ui::CLIPBOARD_TYPE_COPY_PASTE, objects);
     56   }
     57 
     58  protected:
     59   Clipboard& clipboard() { return clipboard_; }
     60 
     61   void WriteObjectsToClipboard(const Clipboard::ObjectMap& objects) {
     62     WriteObjectsToClipboard(&clipboard(), objects);
     63   }
     64 
     65  private:
     66   base::MessageLoopForUI message_loop_;
     67 #if defined(USE_AURA)
     68   scoped_ptr<PlatformEventSource> event_source_;
     69 #endif
     70   Clipboard clipboard_;
     71 };
     72 
     73 namespace {
     74 
     75 bool MarkupMatches(const base::string16& expected_markup,
     76                    const base::string16& actual_markup) {
     77   return actual_markup.find(expected_markup) != base::string16::npos;
     78 }
     79 
     80 }  // namespace
     81 
     82 TEST_F(ClipboardTest, ClearTest) {
     83   {
     84     ScopedClipboardWriter clipboard_writer(&clipboard(),
     85                                            CLIPBOARD_TYPE_COPY_PASTE);
     86     clipboard_writer.WriteText(ASCIIToUTF16("clear me"));
     87   }
     88 
     89   clipboard().Clear(CLIPBOARD_TYPE_COPY_PASTE);
     90 
     91   EXPECT_FALSE(clipboard().IsFormatAvailable(
     92       Clipboard::GetPlainTextWFormatType(), CLIPBOARD_TYPE_COPY_PASTE));
     93   EXPECT_FALSE(clipboard().IsFormatAvailable(
     94       Clipboard::GetPlainTextFormatType(), CLIPBOARD_TYPE_COPY_PASTE));
     95 }
     96 
     97 TEST_F(ClipboardTest, TextTest) {
     98   base::string16 text(ASCIIToUTF16("This is a base::string16!#$")), text_result;
     99   std::string ascii_text;
    100 
    101   {
    102     ScopedClipboardWriter clipboard_writer(&clipboard(),
    103                                            CLIPBOARD_TYPE_COPY_PASTE);
    104     clipboard_writer.WriteText(text);
    105   }
    106 
    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);
    112 
    113   EXPECT_EQ(text, text_result);
    114   clipboard().ReadAsciiText(CLIPBOARD_TYPE_COPY_PASTE, &ascii_text);
    115   EXPECT_EQ(UTF16ToUTF8(text), ascii_text);
    116 }
    117 
    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;
    122 
    123   {
    124     ScopedClipboardWriter clipboard_writer(&clipboard(),
    125                                            CLIPBOARD_TYPE_COPY_PASTE);
    126     clipboard_writer.WriteText(plain);
    127     clipboard_writer.WriteHTML(markup, url);
    128   }
    129 
    130   EXPECT_TRUE(clipboard().IsFormatAvailable(Clipboard::GetHtmlFormatType(),
    131                                             CLIPBOARD_TYPE_COPY_PASTE));
    132   uint32 ignored;
    133   clipboard().ReadHTML(CLIPBOARD_TYPE_COPY_PASTE, &markup_result, &url_result,
    134                      &ignored, &ignored);
    135   EXPECT_PRED2(MarkupMatches, markup, markup_result);
    136 #if defined(OS_WIN)
    137   // TODO(playmobil): It's not clear that non windows clipboards need to support
    138   // this.
    139   EXPECT_EQ(url, url_result);
    140 #endif  // defined(OS_WIN)
    141 }
    142 
    143 TEST_F(ClipboardTest, RTFTest) {
    144   std::string rtf =
    145       "{\\rtf1\\ansi{\\fonttbl\\f0\\fswiss Helvetica;}\\f0\\pard\n"
    146       "This is some {\\b bold} text.\\par\n"
    147       "}";
    148 
    149   {
    150     ScopedClipboardWriter clipboard_writer(&clipboard(),
    151                                            CLIPBOARD_TYPE_COPY_PASTE);
    152     clipboard_writer.WriteRTF(rtf);
    153   }
    154 
    155   EXPECT_TRUE(clipboard().IsFormatAvailable(Clipboard::GetRtfFormatType(),
    156                                             CLIPBOARD_TYPE_COPY_PASTE));
    157   std::string result;
    158   clipboard().ReadRTF(CLIPBOARD_TYPE_COPY_PASTE, &result);
    159   EXPECT_EQ(rtf, result);
    160 }
    161 
    162 // TODO(dnicoara) Enable test once Ozone implements clipboard support:
    163 // crbug.com/361707
    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;
    169 
    170   {
    171     ScopedClipboardWriter clipboard_writer(&clipboard(),
    172                                            CLIPBOARD_TYPE_COPY_PASTE);
    173     clipboard_writer.WriteText(text);
    174   }
    175 
    176   {
    177     ScopedClipboardWriter clipboard_writer(&clipboard(),
    178                                            CLIPBOARD_TYPE_SELECTION);
    179     clipboard_writer.WriteHTML(markup, url);
    180   }
    181 
    182   EXPECT_TRUE(clipboard().IsFormatAvailable(Clipboard::GetPlainTextFormatType(),
    183                                             CLIPBOARD_TYPE_COPY_PASTE));
    184   EXPECT_FALSE(clipboard().IsFormatAvailable(
    185       Clipboard::GetPlainTextFormatType(),
    186       CLIPBOARD_TYPE_SELECTION));
    187 
    188   EXPECT_FALSE(clipboard().IsFormatAvailable(Clipboard::GetHtmlFormatType(),
    189                                              CLIPBOARD_TYPE_COPY_PASTE));
    190   EXPECT_TRUE(clipboard().IsFormatAvailable(Clipboard::GetHtmlFormatType(),
    191                                             CLIPBOARD_TYPE_SELECTION));
    192 
    193   clipboard().ReadText(CLIPBOARD_TYPE_COPY_PASTE, &text_result);
    194   EXPECT_EQ(text, text_result);
    195 
    196   uint32 ignored;
    197   base::string16 markup_result;
    198   clipboard().ReadHTML(CLIPBOARD_TYPE_SELECTION,
    199                        &markup_result,
    200                        &url_result,
    201                        &ignored,
    202                        &ignored);
    203   EXPECT_PRED2(MarkupMatches, markup, markup_result);
    204 }
    205 #endif
    206 
    207 TEST_F(ClipboardTest, TrickyHTMLTest) {
    208   base::string16 markup(ASCIIToUTF16("<em>Bye!<!--EndFragment --></em>")),
    209       markup_result;
    210   std::string url, url_result;
    211   base::string16 plain(ASCIIToUTF16("Bye!")), plain_result;
    212 
    213   {
    214     ScopedClipboardWriter clipboard_writer(&clipboard(),
    215                                            CLIPBOARD_TYPE_COPY_PASTE);
    216     clipboard_writer.WriteText(plain);
    217     clipboard_writer.WriteHTML(markup, url);
    218   }
    219 
    220   EXPECT_TRUE(clipboard().IsFormatAvailable(Clipboard::GetHtmlFormatType(),
    221                                             CLIPBOARD_TYPE_COPY_PASTE));
    222   uint32 ignored;
    223   clipboard().ReadHTML(CLIPBOARD_TYPE_COPY_PASTE, &markup_result, &url_result,
    224                        &ignored, &ignored);
    225   EXPECT_PRED2(MarkupMatches, markup, markup_result);
    226 #if defined(OS_WIN)
    227   // TODO(playmobil): It's not clear that non windows clipboards need to support
    228   // this.
    229   EXPECT_EQ(url, url_result);
    230 #endif  // defined(OS_WIN)
    231 }
    232 
    233 #if defined(OS_WIN)
    234 TEST_F(ClipboardTest, UniodeHTMLTest) {
    235   base::string16 markup(UTF8ToUTF16("<div>A \xc3\xb8 \xe6\xb0\xb4</div>")),
    236       markup_result;
    237   std::string url, url_result;
    238 
    239   {
    240     ScopedClipboardWriter clipboard_writer(&clipboard(),
    241                                            CLIPBOARD_TYPE_COPY_PASTE);
    242     clipboard_writer.WriteHTML(markup, url);
    243   }
    244 
    245   EXPECT_TRUE(clipboard().IsFormatAvailable(Clipboard::GetHtmlFormatType(),
    246                                             CLIPBOARD_TYPE_COPY_PASTE));
    247   uint32 fragment_start;
    248   uint32 fragment_end;
    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);
    256 }
    257 #endif  // defined(OS_WIN)
    258 
    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;
    264 
    265   {
    266     ScopedClipboardWriter clipboard_writer(&clipboard(),
    267                                            CLIPBOARD_TYPE_COPY_PASTE);
    268     clipboard_writer.WriteBookmark(title, url);
    269   }
    270 
    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);
    276 }
    277 #endif  // defined(OS_WIN)
    278 
    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;
    284 
    285   {
    286     ScopedClipboardWriter clipboard_writer(&clipboard(),
    287                                            CLIPBOARD_TYPE_COPY_PASTE);
    288     clipboard_writer.WriteHTML(markup, url);
    289     clipboard_writer.WriteText(text);
    290   }
    291 
    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));
    298   uint32 ignored;
    299   clipboard().ReadHTML(CLIPBOARD_TYPE_COPY_PASTE, &markup_result, &url_result,
    300                        &ignored, &ignored);
    301   EXPECT_PRED2(MarkupMatches, markup, markup_result);
    302 #if defined(OS_WIN)
    303   // TODO(playmobil): It's not clear that non windows clipboards need to support
    304   // this.
    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);
    311 }
    312 
    313 TEST_F(ClipboardTest, URLTest) {
    314   base::string16 url(ASCIIToUTF16("http://www.google.com/"));
    315 
    316   {
    317     ScopedClipboardWriter clipboard_writer(&clipboard(),
    318                                            CLIPBOARD_TYPE_COPY_PASTE);
    319     clipboard_writer.WriteURL(url);
    320   }
    321 
    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);
    328 
    329   EXPECT_EQ(text_result, url);
    330 
    331   std::string ascii_text;
    332   clipboard().ReadAsciiText(CLIPBOARD_TYPE_COPY_PASTE, &ascii_text);
    333   EXPECT_EQ(UTF16ToUTF8(url), ascii_text);
    334 
    335 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
    336   ascii_text.clear();
    337   clipboard().ReadAsciiText(CLIPBOARD_TYPE_SELECTION, &ascii_text);
    338   EXPECT_EQ(UTF16ToUTF8(url), ascii_text);
    339 #endif
    340 }
    341 
    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);
    360     }
    361   }
    362   base::SharedMemoryHandle handle_to_share;
    363   base::ProcessHandle current_process = base::kNullProcessHandle;
    364 #if defined(OS_WIN)
    365   current_process = GetCurrentProcess();
    366 #endif
    367   shared_buf.ShareToProcess(current_process, &handle_to_share);
    368   ASSERT_TRUE(shared_buf.Unmap());
    369 
    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]);
    376 
    377   Clipboard::ObjectMapParams params;
    378   params.push_back(placeholder_param);
    379   params.push_back(size_param);
    380 
    381   Clipboard::ObjectMap objects;
    382   objects[Clipboard::CBF_SMBITMAP] = params;
    383   ASSERT_TRUE(Clipboard::ReplaceSharedMemHandle(
    384       &objects, handle_to_share, current_process));
    385 
    386   ClipboardTest::WriteObjectsToClipboard(clipboard, objects);
    387 
    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;
    400     }
    401   }
    402 }
    403 
    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,
    409   };
    410   {
    411     SCOPED_TRACE("first bitmap");
    412     TestBitmapWrite(
    413         &clipboard(), fake_bitmap_1, sizeof(fake_bitmap_1), gfx::Size(4, 3));
    414   }
    415 
    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,
    424   };
    425   {
    426     SCOPED_TRACE("second bitmap");
    427     TestBitmapWrite(
    428         &clipboard(), fake_bitmap_2, sizeof(fake_bitmap_2), gfx::Size(2, 7));
    429   }
    430 }
    431 
    432 namespace {
    433 // A size class that just happens to have the same layout as gfx::Size!
    434 struct UnsafeSize {
    435   int width;
    436   int height;
    437 };
    438 COMPILE_ASSERT(sizeof(UnsafeSize) == sizeof(gfx::Size),
    439                UnsafeSize_must_be_same_size_as_gfx_Size);
    440 }  // namespace
    441 
    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));
    447 
    448   Clipboard::ObjectMapParam size_param;
    449   UnsafeSize size = {-100, -100};
    450   size_param.resize(sizeof(size));
    451   memcpy(&size_param.front(), &size, sizeof(size));
    452 
    453   Clipboard::ObjectMapParams params;
    454   params.push_back(placeholder_param);
    455   params.push_back(size_param);
    456 
    457   Clipboard::ObjectMap objects;
    458   objects[Clipboard::CBF_SMBITMAP] = params;
    459 
    460   WriteObjectsToClipboard(objects);
    461   EXPECT_FALSE(clipboard().IsFormatAvailable(Clipboard::GetBitmapFormatType(),
    462                                              CLIPBOARD_TYPE_COPY_PASTE));
    463 }
    464 
    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));
    470 
    471   Clipboard::ObjectMapParam size_param;
    472   UnsafeSize size = {-100, 100};
    473   size_param.resize(sizeof(size));
    474   memcpy(&size_param.front(), &size, sizeof(size));
    475 
    476   Clipboard::ObjectMapParams params;
    477   params.push_back(placeholder_param);
    478   params.push_back(size_param);
    479 
    480   Clipboard::ObjectMap objects;
    481   objects[Clipboard::CBF_SMBITMAP] = params;
    482 
    483   WriteObjectsToClipboard(objects);
    484   EXPECT_FALSE(clipboard().IsFormatAvailable(Clipboard::GetBitmapFormatType(),
    485                                              CLIPBOARD_TYPE_COPY_PASTE));
    486 }
    487 
    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));
    493 
    494   Clipboard::ObjectMapParam size_param;
    495   // Width just big enough that bytes per row won't fit in a 32-bit
    496   // representation.
    497   gfx::Size size(0x20000000, 1);
    498   size_param.resize(sizeof(size));
    499   memcpy(&size_param.front(), &size, sizeof(size));
    500 
    501   Clipboard::ObjectMapParams params;
    502   params.push_back(placeholder_param);
    503   params.push_back(size_param);
    504 
    505   Clipboard::ObjectMap objects;
    506   objects[Clipboard::CBF_SMBITMAP] = params;
    507 
    508   WriteObjectsToClipboard(objects);
    509   EXPECT_FALSE(clipboard().IsFormatAvailable(Clipboard::GetBitmapFormatType(),
    510                                              CLIPBOARD_TYPE_COPY_PASTE));
    511 }
    512 
    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));
    518 
    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));
    524 
    525   Clipboard::ObjectMapParams params;
    526   params.push_back(placeholder_param);
    527   params.push_back(size_param);
    528 
    529   Clipboard::ObjectMap objects;
    530   objects[Clipboard::CBF_SMBITMAP] = params;
    531 
    532   WriteObjectsToClipboard(objects);
    533   EXPECT_FALSE(clipboard().IsFormatAvailable(Clipboard::GetBitmapFormatType(),
    534                                              CLIPBOARD_TYPE_COPY_PASTE));
    535 }
    536 
    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");
    541   Pickle write_pickle;
    542   write_pickle.WriteString(payload);
    543 
    544   {
    545     ScopedClipboardWriter clipboard_writer(&clipboard(),
    546                                            CLIPBOARD_TYPE_COPY_PASTE);
    547     clipboard_writer.WritePickledData(write_pickle, kFormat);
    548   }
    549 
    550   ASSERT_TRUE(clipboard().IsFormatAvailable(
    551       kFormat, CLIPBOARD_TYPE_COPY_PASTE));
    552   std::string output;
    553   clipboard().ReadData(kFormat, &output);
    554   ASSERT_FALSE(output.empty());
    555 
    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);
    561 }
    562 
    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);
    569 
    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);
    575 
    576   {
    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);
    582   }
    583 
    584   ASSERT_TRUE(clipboard().IsFormatAvailable(
    585       kFormat2, CLIPBOARD_TYPE_COPY_PASTE));
    586 
    587   // Check string 2.
    588   std::string output2;
    589   clipboard().ReadData(kFormat2, &output2);
    590   ASSERT_FALSE(output2.empty());
    591 
    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);
    597 
    598   {
    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);
    604   }
    605 
    606   ASSERT_TRUE(clipboard().IsFormatAvailable(
    607       kFormat1, CLIPBOARD_TYPE_COPY_PASTE));
    608 
    609   // Check string 1.
    610   std::string output1;
    611   clipboard().ReadData(kFormat1, &output1);
    612   ASSERT_FALSE(output1.empty());
    613 
    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);
    619 }
    620 
    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#&quot;&#39;&lt;&gt;\">"
    627       "The &lt;Example&gt; Company&#39;s &quot;home page&quot;</a>");
    628 
    629   std::string url_result;
    630   base::string16 html_result;
    631   {
    632     ScopedClipboardWriter clipboard_writer(&clipboard(),
    633                                            CLIPBOARD_TYPE_COPY_PASTE);
    634     clipboard_writer.WriteHyperlink(ASCIIToUTF16(kTitle), kUrl);
    635   }
    636 
    637   EXPECT_TRUE(clipboard().IsFormatAvailable(Clipboard::GetHtmlFormatType(),
    638                                             CLIPBOARD_TYPE_COPY_PASTE));
    639   uint32 ignored;
    640   clipboard().ReadHTML(CLIPBOARD_TYPE_COPY_PASTE, &html_result, &url_result,
    641                        &ignored, &ignored);
    642   EXPECT_PRED2(MarkupMatches, ASCIIToUTF16(kExpectedHtml), html_result);
    643 }
    644 #endif
    645 
    646 #if defined(OS_WIN)  // Windows only tests.
    647 TEST_F(ClipboardTest, WebSmartPasteTest) {
    648   {
    649     ScopedClipboardWriter clipboard_writer(&clipboard(),
    650                                            CLIPBOARD_TYPE_COPY_PASTE);
    651     clipboard_writer.WriteWebSmartPaste();
    652   }
    653 
    654   EXPECT_TRUE(clipboard().IsFormatAvailable(
    655       Clipboard::GetWebKitSmartPasteFormatType(), CLIPBOARD_TYPE_COPY_PASTE));
    656 }
    657 
    658 void HtmlTestHelper(const std::string& cf_html,
    659                     const std::string& expected_html) {
    660   std::string html;
    661   ClipboardUtil::CFHtmlToHtml(cf_html, &html, NULL);
    662   EXPECT_EQ(html, expected_html);
    663 }
    664 
    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"
    673                  "\r\n"
    674                  "<html>\r\n"
    675                  "<body>\r\n"
    676                  "<!--StartFragment-->\r\n"
    677                  "\r\n"
    678                  "<p>Foo</p>\r\n"
    679                  "\r\n"
    680                  "<!--EndFragment-->\r\n"
    681                  "</body>\r\n"
    682                  "</html>\r\n\r\n",
    683                  "<p>Foo</p>");
    684 
    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"
    692                  "<html>\r\n"
    693                  "<body>\r\n"
    694                  "<p>Foo</p>\r\n"
    695                  "</body>\r\n"
    696                  "</html>\r\n\r\n",
    697                  "<p>Foo</p>");
    698 }
    699 #endif  // defined(OS_WIN)
    700 
    701 // Test writing all formats we have simultaneously.
    702 TEST_F(ClipboardTest, WriteEverything) {
    703   {
    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.
    712   }
    713 
    714   // Passes if we don't crash.
    715 }
    716 
    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
    723 // written to.
    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);
    728 
    729   {
    730     ScopedClipboardWriter writer(&clipboard(), CLIPBOARD_TYPE_COPY_PASTE);
    731     writer.WriteText(UTF8ToUTF16("World"));
    732   }
    733 
    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();
    737 
    738   const uint64 second_sequence_number =
    739       clipboard().GetSequenceNumber(CLIPBOARD_TYPE_COPY_PASTE);
    740 
    741   EXPECT_NE(first_sequence_number, second_sequence_number);
    742 }
    743 #endif
    744 
    745 #if defined(OS_ANDROID)
    746 
    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.
    751   {
    752     ScopedClipboardWriter clipboard_writer(&clipboard(),
    753                                            CLIPBOARD_TYPE_COPY_PASTE);
    754     clipboard_writer.WriteWebSmartPaste();
    755   }
    756   EXPECT_TRUE(clipboard().IsFormatAvailable(
    757       Clipboard::GetWebKitSmartPasteFormatType(), CLIPBOARD_TYPE_COPY_PASTE));
    758 
    759   //
    760   // Simulate that another application copied something in the Clipboard
    761   //
    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;
    766 
    767   JNIEnv* env = base::android::AttachCurrentThread();
    768   ASSERT_TRUE(env);
    769 
    770   jobject context = base::android::GetApplicationContext();
    771   ASSERT_TRUE(context);
    772 
    773   ScopedJavaLocalRef<jclass> context_class =
    774       base::android::GetClass(env, "android/content/Context");
    775 
    776   jmethodID get_system_service = MethodID::Get<MethodID::TYPE_INSTANCE>(
    777       env, context_class.obj(), "getSystemService",
    778       "(Ljava/lang/String;)Ljava/lang/Object;");
    779 
    780   // Retrieve the system service.
    781   ScopedJavaLocalRef<jstring> service_name = ConvertUTF8ToJavaString(
    782       env, "clipboard");
    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));
    787 
    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());
    794 
    795   // Will need to call toString as CharSequence is not always a String.
    796   env->CallVoidMethod(clipboard_manager.obj(),
    797                       set_text,
    798                       new_value_string.obj());
    799 
    800   // The WebKit smart paste tag should now be gone.
    801   EXPECT_FALSE(clipboard().IsFormatAvailable(
    802       Clipboard::GetWebKitSmartPasteFormatType(), CLIPBOARD_TYPE_COPY_PASTE));
    803 
    804   // Make sure some text is available
    805   EXPECT_TRUE(clipboard().IsFormatAvailable(
    806       Clipboard::GetPlainTextWFormatType(), CLIPBOARD_TYPE_COPY_PASTE));
    807 
    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);
    812 }
    813 #endif
    814 }  // namespace ui
    815