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/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 
     34 namespace ui {
     35 
     36 class ClipboardTest : public PlatformTest {
     37  protected:
     38   Clipboard& clipboard() { return clipboard_; }
     39 
     40  private:
     41   base::MessageLoopForUI message_loop_;
     42   Clipboard clipboard_;
     43 };
     44 
     45 namespace {
     46 
     47 bool MarkupMatches(const string16& expected_markup,
     48                    const string16& actual_markup) {
     49   return actual_markup.find(expected_markup) != string16::npos;
     50 }
     51 
     52 }  // namespace
     53 
     54 TEST_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 
     69 TEST_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 
     90 TEST_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 
    115 TEST_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)
    135 TEST_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 
    176 TEST_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)
    203 TEST_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).
    230 TEST_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)
    251 TEST_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 
    269 TEST_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 
    303 TEST_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!
    333 static 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 
    402 TEST_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 
    430 namespace {
    431 // A size class that just happens to have the same layout as gfx::Size!
    432 struct UnsafeSize {
    433   int width;
    434   int height;
    435 };
    436 COMPILE_ASSERT(sizeof(UnsafeSize) == sizeof(gfx::Size),
    437                UnsafeSize_must_be_same_size_as_gfx_Size);
    438 }  // namespace
    439 
    440 TEST_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 
    463 TEST_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 
    486 TEST_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 
    511 TEST_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 
    535 TEST_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 
    561 TEST_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)
    620 TEST_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&lt=3#&quot;&#39;&lt;&gt;\">"
    625       "The &lt;Example&gt; Company&#39;s &quot;home page&quot;</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.
    645 TEST_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 
    656 void 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 
    663 TEST_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.
    700 TEST_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.
    719 TEST_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