Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / ui / base / clipboard / clipboard_win.cc
index 36d042d..b46aba5 100644 (file)
@@ -5,7 +5,7 @@
 // Many of these functions are based on those found in
 // webkit/port/platform/PasteboardWin.cpp
 
-#include "ui/base/clipboard/clipboard.h"
+#include "ui/base/clipboard/clipboard_win.h"
 
 #include <shellapi.h>
 #include <shlobj.h>
@@ -136,7 +136,7 @@ HGLOBAL CreateGlobalData(const std::basic_string<charT>& str) {
     ::GlobalUnlock(data);
   }
   return data;
-};
+}
 
 bool BitmapHasInvalidPremultipliedColors(const SkBitmap& bitmap) {
   for (int x = 0; x < bitmap.width(); ++x) {
@@ -159,14 +159,40 @@ void MakeBitmapOpaque(const SkBitmap& bitmap) {
   }
 }
 
+void ParseBookmarkClipboardFormat(const base::string16& bookmark,
+                                  base::string16* title,
+                                  std::string* url) {
+  const base::string16 kDelim = base::ASCIIToUTF16("\r\n");
+
+  const size_t title_end = bookmark.find_first_of(kDelim);
+  if (title)
+    title->assign(bookmark.substr(0, title_end));
+
+  if (url) {
+    const size_t url_start = bookmark.find_first_not_of(kDelim, title_end);
+    if (url_start != base::string16::npos) {
+      *url =
+          base::UTF16ToUTF8(bookmark.substr(url_start, base::string16::npos));
+    }
+  }
+}
+
+void FreeData(unsigned int format, HANDLE data) {
+  if (format == CF_BITMAP)
+    ::DeleteObject(static_cast<HBITMAP>(data));
+  else
+    ::GlobalFree(data);
+}
+
 }  // namespace
 
+// Clipboard::FormatType implementation.
 Clipboard::FormatType::FormatType() : data_() {}
 
 Clipboard::FormatType::FormatType(UINT native_format) : data_() {
   // There's no good way to actually initialize this in the constructor in
   // C++03.
-  data_.cfFormat = native_format;
+  data_.cfFormat = static_cast<CLIPFORMAT>(native_format);
   data_.dwAspect = DVASPECT_CONTENT;
   data_.lindex = -1;
   data_.tymed = TYMED_HGLOBAL;
@@ -175,7 +201,7 @@ Clipboard::FormatType::FormatType(UINT native_format) : data_() {
 Clipboard::FormatType::FormatType(UINT native_format, LONG index) : data_() {
   // There's no good way to actually initialize this in the constructor in
   // C++03.
-  data_.cfFormat = native_format;
+  data_.cfFormat = static_cast<CLIPFORMAT>(native_format);
   data_.dwAspect = DVASPECT_CONTENT;
   data_.lindex = index;
   data_.tymed = TYMED_HGLOBAL;
@@ -200,196 +226,180 @@ Clipboard::FormatType Clipboard::FormatType::Deserialize(
 }
 
 bool Clipboard::FormatType::operator<(const FormatType& other) const {
-  return ToUINT() < other.ToUINT();
+  return data_.cfFormat < other.data_.cfFormat;
 }
 
 bool Clipboard::FormatType::Equals(const FormatType& other) const {
-  return ToUINT() == other.ToUINT();
+  return data_.cfFormat == other.data_.cfFormat;
 }
 
-Clipboard::Clipboard() {
-  if (base::MessageLoopForUI::IsCurrent())
-    clipboard_owner_.reset(new base::win::MessageWindow());
+// Various predefined FormatTypes.
+// static
+Clipboard::FormatType Clipboard::GetFormatType(
+    const std::string& format_string) {
+  return FormatType(
+      ::RegisterClipboardFormat(base::ASCIIToUTF16(format_string).c_str()));
 }
 
-Clipboard::~Clipboard() {
+// static
+const Clipboard::FormatType& Clipboard::GetUrlFormatType() {
+  CR_DEFINE_STATIC_LOCAL(
+      FormatType, type, (::RegisterClipboardFormat(CFSTR_INETURLA)));
+  return type;
 }
 
-void Clipboard::WriteObjects(ClipboardType type, const ObjectMap& objects) {
-  DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
-
-  ScopedClipboard clipboard;
-  if (!clipboard.Acquire(GetClipboardWindow()))
-    return;
-
-  ::EmptyClipboard();
-
-  for (ObjectMap::const_iterator iter = objects.begin();
-       iter != objects.end(); ++iter) {
-    DispatchObject(static_cast<ObjectType>(iter->first), iter->second);
-  }
+// static
+const Clipboard::FormatType& Clipboard::GetUrlWFormatType() {
+  CR_DEFINE_STATIC_LOCAL(
+      FormatType, type, (::RegisterClipboardFormat(CFSTR_INETURLW)));
+  return type;
 }
 
-void Clipboard::WriteText(const char* text_data, size_t text_len) {
-  base::string16 text;
-  base::UTF8ToUTF16(text_data, text_len, &text);
-  HGLOBAL glob = CreateGlobalData(text);
-
-  WriteToClipboard(CF_UNICODETEXT, glob);
+// static
+const Clipboard::FormatType& Clipboard::GetMozUrlFormatType() {
+  CR_DEFINE_STATIC_LOCAL(
+      FormatType, type, (::RegisterClipboardFormat(L"text/x-moz-url")));
+  return type;
 }
 
-void Clipboard::WriteHTML(const char* markup_data,
-                          size_t markup_len,
-                          const char* url_data,
-                          size_t url_len) {
-  std::string markup(markup_data, markup_len);
-  std::string url;
-
-  if (url_len > 0)
-    url.assign(url_data, url_len);
-
-  std::string html_fragment = ClipboardUtil::HtmlToCFHtml(markup, url);
-  HGLOBAL glob = CreateGlobalData(html_fragment);
-
-  WriteToClipboard(Clipboard::GetHtmlFormatType().ToUINT(), glob);
+// static
+const Clipboard::FormatType& Clipboard::GetPlainTextFormatType() {
+  CR_DEFINE_STATIC_LOCAL(FormatType, type, (CF_TEXT));
+  return type;
 }
 
-void Clipboard::WriteRTF(const char* rtf_data, size_t data_len) {
-  WriteData(GetRtfFormatType(), rtf_data, data_len);
+// static
+const Clipboard::FormatType& Clipboard::GetPlainTextWFormatType() {
+  CR_DEFINE_STATIC_LOCAL(FormatType, type, (CF_UNICODETEXT));
+  return type;
 }
 
-void Clipboard::WriteBookmark(const char* title_data,
-                              size_t title_len,
-                              const char* url_data,
-                              size_t url_len) {
-  std::string bookmark(title_data, title_len);
-  bookmark.append(1, L'\n');
-  bookmark.append(url_data, url_len);
-
-  base::string16 wide_bookmark = base::UTF8ToWide(bookmark);
-  HGLOBAL glob = CreateGlobalData(wide_bookmark);
-
-  WriteToClipboard(GetUrlWFormatType().ToUINT(), glob);
+// static
+const Clipboard::FormatType& Clipboard::GetFilenameFormatType() {
+  CR_DEFINE_STATIC_LOCAL(
+      FormatType, type, (::RegisterClipboardFormat(CFSTR_FILENAMEA)));
+  return type;
 }
 
-void Clipboard::WriteWebSmartPaste() {
-  DCHECK(clipboard_owner_->hwnd() != NULL);
-  ::SetClipboardData(GetWebKitSmartPasteFormatType().ToUINT(), NULL);
+// static
+const Clipboard::FormatType& Clipboard::GetFilenameWFormatType() {
+  CR_DEFINE_STATIC_LOCAL(
+      FormatType, type, (::RegisterClipboardFormat(CFSTR_FILENAMEW)));
+  return type;
 }
 
-void Clipboard::WriteBitmap(const SkBitmap& bitmap) {
-  HDC dc = ::GetDC(NULL);
-
-  // This doesn't actually cost us a memcpy when the bitmap comes from the
-  // renderer as we load it into the bitmap using setPixels which just sets a
-  // pointer.  Someone has to memcpy it into GDI, it might as well be us here.
-
-  // TODO(darin): share data in gfx/bitmap_header.cc somehow
-  BITMAPINFO bm_info = {0};
-  bm_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
-  bm_info.bmiHeader.biWidth = bitmap.width();
-  bm_info.bmiHeader.biHeight = -bitmap.height();  // sets vertical orientation
-  bm_info.bmiHeader.biPlanes = 1;
-  bm_info.bmiHeader.biBitCount = 32;
-  bm_info.bmiHeader.biCompression = BI_RGB;
-
-  // ::CreateDIBSection allocates memory for us to copy our bitmap into.
-  // Unfortunately, we can't write the created bitmap to the clipboard,
-  // (see http://msdn2.microsoft.com/en-us/library/ms532292.aspx)
-  void *bits;
-  HBITMAP source_hbitmap =
-      ::CreateDIBSection(dc, &bm_info, DIB_RGB_COLORS, &bits, NULL, 0);
+// MS HTML Format
+// static
+const Clipboard::FormatType& Clipboard::GetHtmlFormatType() {
+  CR_DEFINE_STATIC_LOCAL(
+      FormatType, type, (::RegisterClipboardFormat(L"HTML Format")));
+  return type;
+}
 
-  if (bits && source_hbitmap) {
-    {
-      SkAutoLockPixels bitmap_lock(bitmap);
-      // Copy the bitmap out of shared memory and into GDI
-      memcpy(bits, bitmap.getPixels(), bitmap.getSize());
-    }
+// MS RTF Format
+// static
+const Clipboard::FormatType& Clipboard::GetRtfFormatType() {
+  CR_DEFINE_STATIC_LOCAL(
+      FormatType, type, (::RegisterClipboardFormat(L"Rich Text Format")));
+  return type;
+}
 
-    // Now we have an HBITMAP, we can write it to the clipboard
-    WriteBitmapFromHandle(source_hbitmap,
-                          gfx::Size(bitmap.width(), bitmap.height()));
-  }
+// static
+const Clipboard::FormatType& Clipboard::GetBitmapFormatType() {
+  CR_DEFINE_STATIC_LOCAL(FormatType, type, (CF_BITMAP));
+  return type;
+}
 
-  ::DeleteObject(source_hbitmap);
-  ::ReleaseDC(NULL, dc);
+// Firefox text/html
+// static
+const Clipboard::FormatType& Clipboard::GetTextHtmlFormatType() {
+  CR_DEFINE_STATIC_LOCAL(
+      FormatType, type, (::RegisterClipboardFormat(L"text/html")));
+  return type;
 }
 
-void Clipboard::WriteBitmapFromHandle(HBITMAP source_hbitmap,
-                                      const gfx::Size& size) {
-  // We would like to just call ::SetClipboardData on the source_hbitmap,
-  // but that bitmap might not be of a sort we can write to the clipboard.
-  // For this reason, we create a new bitmap, copy the bits over, and then
-  // write that to the clipboard.
+// static
+const Clipboard::FormatType& Clipboard::GetCFHDropFormatType() {
+  CR_DEFINE_STATIC_LOCAL(FormatType, type, (CF_HDROP));
+  return type;
+}
 
-  HDC dc = ::GetDC(NULL);
-  HDC compatible_dc = ::CreateCompatibleDC(NULL);
-  HDC source_dc = ::CreateCompatibleDC(NULL);
+// static
+const Clipboard::FormatType& Clipboard::GetFileDescriptorFormatType() {
+  CR_DEFINE_STATIC_LOCAL(
+      FormatType, type, (::RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR)));
+  return type;
+}
 
-  // This is the HBITMAP we will eventually write to the clipboard
-  HBITMAP hbitmap = ::CreateCompatibleBitmap(dc, size.width(), size.height());
-  if (!hbitmap) {
-    // Failed to create the bitmap
-    ::DeleteDC(compatible_dc);
-    ::DeleteDC(source_dc);
-    ::ReleaseDC(NULL, dc);
-    return;
-  }
+// static
+const Clipboard::FormatType& Clipboard::GetFileContentZeroFormatType() {
+  CR_DEFINE_STATIC_LOCAL(
+      FormatType, type, (::RegisterClipboardFormat(CFSTR_FILECONTENTS), 0));
+  return type;
+}
 
-  HBITMAP old_hbitmap = (HBITMAP)SelectObject(compatible_dc, hbitmap);
-  HBITMAP old_source = (HBITMAP)SelectObject(source_dc, source_hbitmap);
+// static
+const Clipboard::FormatType& Clipboard::GetIDListFormatType() {
+  CR_DEFINE_STATIC_LOCAL(
+      FormatType, type, (::RegisterClipboardFormat(CFSTR_SHELLIDLIST)));
+  return type;
+}
 
-  // Now we need to blend it into an HBITMAP we can place on the clipboard
-  BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA};
-  ::GdiAlphaBlend(compatible_dc, 0, 0, size.width(), size.height(),
-                  source_dc, 0, 0, size.width(), size.height(), bf);
+// static
+const Clipboard::FormatType& Clipboard::GetWebKitSmartPasteFormatType() {
+  CR_DEFINE_STATIC_LOCAL(
+      FormatType,
+      type,
+      (::RegisterClipboardFormat(L"WebKit Smart Paste Format")));
+  return type;
+}
 
-  // Clean up all the handles we just opened
-  ::SelectObject(compatible_dc, old_hbitmap);
-  ::SelectObject(source_dc, old_source);
-  ::DeleteObject(old_hbitmap);
-  ::DeleteObject(old_source);
-  ::DeleteDC(compatible_dc);
-  ::DeleteDC(source_dc);
-  ::ReleaseDC(NULL, dc);
+// static
+const Clipboard::FormatType& Clipboard::GetWebCustomDataFormatType() {
+  // TODO(dcheng): This name is temporary. See http://crbug.com/106449.
+  CR_DEFINE_STATIC_LOCAL(
+      FormatType,
+      type,
+      (::RegisterClipboardFormat(L"Chromium Web Custom MIME Data Format")));
+  return type;
+}
 
-  WriteToClipboard(CF_BITMAP, hbitmap);
+// static
+const Clipboard::FormatType& Clipboard::GetPepperCustomDataFormatType() {
+  CR_DEFINE_STATIC_LOCAL(
+      FormatType,
+      type,
+      (::RegisterClipboardFormat(L"Chromium Pepper MIME Data Format")));
+  return type;
 }
 
-void Clipboard::WriteData(const FormatType& format,
-                          const char* data_data,
-                          size_t data_len) {
-  HGLOBAL hdata = ::GlobalAlloc(GMEM_MOVEABLE, data_len);
-  if (!hdata)
-    return;
+// Clipboard factory method.
+// static
+Clipboard* Clipboard::Create() {
+  return new ClipboardWin;
+}
 
-  char* data = static_cast<char*>(::GlobalLock(hdata));
-  memcpy(data, data_data, data_len);
-  ::GlobalUnlock(data);
-  WriteToClipboard(format.ToUINT(), hdata);
+// ClipboardWin implementation.
+ClipboardWin::ClipboardWin() {
+  if (base::MessageLoopForUI::IsCurrent())
+    clipboard_owner_.reset(new base::win::MessageWindow());
 }
 
-void Clipboard::WriteToClipboard(unsigned int format, HANDLE handle) {
-  DCHECK(clipboard_owner_->hwnd() != NULL);
-  if (handle && !::SetClipboardData(format, handle)) {
-    DCHECK(ERROR_CLIPBOARD_NOT_OPEN != GetLastError());
-    FreeData(format, handle);
-  }
+ClipboardWin::~ClipboardWin() {
 }
 
-uint64 Clipboard::GetSequenceNumber(ClipboardType type) {
+uint64 ClipboardWin::GetSequenceNumber(ClipboardType type) {
   DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
   return ::GetClipboardSequenceNumber();
 }
 
-bool Clipboard::IsFormatAvailable(const Clipboard::FormatType& format,
-                                  ClipboardType type) const {
+bool ClipboardWin::IsFormatAvailable(const Clipboard::FormatType& format,
+                                     ClipboardType type) const {
   DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
-  return ::IsClipboardFormatAvailable(format.ToUINT()) != FALSE;
+  return ::IsClipboardFormatAvailable(format.ToFormatEtc().cfFormat) != FALSE;
 }
 
-void Clipboard::Clear(ClipboardType type) {
+void ClipboardWin::Clear(ClipboardType type) {
   DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
   ScopedClipboard clipboard;
   if (!clipboard.Acquire(GetClipboardWindow()))
@@ -398,20 +408,21 @@ void Clipboard::Clear(ClipboardType type) {
   ::EmptyClipboard();
 }
 
-void Clipboard::ReadAvailableTypes(ClipboardType type,
-                                   std::vector<base::string16>* types,
-                                   bool* contains_filenames) const {
+void ClipboardWin::ReadAvailableTypes(ClipboardType type,
+                                      std::vector<base::string16>* types,
+                                      bool* contains_filenames) const {
   if (!types || !contains_filenames) {
     NOTREACHED();
     return;
   }
 
   types->clear();
-  if (::IsClipboardFormatAvailable(GetPlainTextFormatType().ToUINT()))
+  if (::IsClipboardFormatAvailable(
+          GetPlainTextFormatType().ToFormatEtc().cfFormat))
     types->push_back(base::UTF8ToUTF16(kMimeTypeText));
-  if (::IsClipboardFormatAvailable(GetHtmlFormatType().ToUINT()))
+  if (::IsClipboardFormatAvailable(GetHtmlFormatType().ToFormatEtc().cfFormat))
     types->push_back(base::UTF8ToUTF16(kMimeTypeHTML));
-  if (::IsClipboardFormatAvailable(GetRtfFormatType().ToUINT()))
+  if (::IsClipboardFormatAvailable(GetRtfFormatType().ToFormatEtc().cfFormat))
     types->push_back(base::UTF8ToUTF16(kMimeTypeRTF));
   if (::IsClipboardFormatAvailable(CF_DIB))
     types->push_back(base::UTF8ToUTF16(kMimeTypePNG));
@@ -422,7 +433,8 @@ void Clipboard::ReadAvailableTypes(ClipboardType type,
   if (!clipboard.Acquire(GetClipboardWindow()))
     return;
 
-  HANDLE hdata = ::GetClipboardData(GetWebCustomDataFormatType().ToUINT());
+  HANDLE hdata =
+      ::GetClipboardData(GetWebCustomDataFormatType().ToFormatEtc().cfFormat);
   if (!hdata)
     return;
 
@@ -430,7 +442,7 @@ void Clipboard::ReadAvailableTypes(ClipboardType type,
   ::GlobalUnlock(hdata);
 }
 
-void Clipboard::ReadText(ClipboardType type, base::string16* result) const {
+void ClipboardWin::ReadText(ClipboardType type, base::string16* result) const {
   DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
   if (!result) {
     NOTREACHED();
@@ -452,7 +464,8 @@ void Clipboard::ReadText(ClipboardType type, base::string16* result) const {
   ::GlobalUnlock(data);
 }
 
-void Clipboard::ReadAsciiText(ClipboardType type, std::string* result) const {
+void ClipboardWin::ReadAsciiText(ClipboardType type,
+                                 std::string* result) const {
   DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
   if (!result) {
     NOTREACHED();
@@ -474,11 +487,11 @@ void Clipboard::ReadAsciiText(ClipboardType type, std::string* result) const {
   ::GlobalUnlock(data);
 }
 
-void Clipboard::ReadHTML(ClipboardType type,
-                         base::string16* markup,
-                         std::string* src_url,
-                         uint32* fragment_start,
-                         uint32* fragment_end) const {
+void ClipboardWin::ReadHTML(ClipboardType type,
+                            base::string16* markup,
+                            std::string* src_url,
+                            uint32* fragment_start,
+                            uint32* fragment_end) const {
   DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
 
   markup->clear();
@@ -494,7 +507,7 @@ void Clipboard::ReadHTML(ClipboardType type,
   if (!clipboard.Acquire(GetClipboardWindow()))
     return;
 
-  HANDLE data = ::GetClipboardData(GetHtmlFormatType().ToUINT());
+  HANDLE data = ::GetClipboardData(GetHtmlFormatType().ToFormatEtc().cfFormat);
   if (!data)
     return;
 
@@ -526,13 +539,13 @@ void Clipboard::ReadHTML(ClipboardType type,
   *fragment_end = base::checked_cast<uint32>(offsets[1]);
 }
 
-void Clipboard::ReadRTF(ClipboardType type, std::string* result) const {
+void ClipboardWin::ReadRTF(ClipboardType type, std::string* result) const {
   DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
 
   ReadData(GetRtfFormatType(), result);
 }
 
-SkBitmap Clipboard::ReadImage(ClipboardType type) const {
+SkBitmap ClipboardWin::ReadImage(ClipboardType type) const {
   DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
 
   // Acquire the clipboard.
@@ -602,9 +615,9 @@ SkBitmap Clipboard::ReadImage(ClipboardType type) const {
   return canvas.ExtractImageRep().sk_bitmap();
 }
 
-void Clipboard::ReadCustomData(ClipboardType clipboard_type,
-                               const base::string16& type,
-                               base::string16* result) const {
+void ClipboardWin::ReadCustomData(ClipboardType clipboard_type,
+                                  const base::string16& type,
+                                  base::string16* result) const {
   DCHECK_EQ(clipboard_type, CLIPBOARD_TYPE_COPY_PASTE);
 
   // Acquire the clipboard.
@@ -612,7 +625,8 @@ void Clipboard::ReadCustomData(ClipboardType clipboard_type,
   if (!clipboard.Acquire(GetClipboardWindow()))
     return;
 
-  HANDLE hdata = ::GetClipboardData(GetWebCustomDataFormatType().ToUINT());
+  HANDLE hdata =
+      ::GetClipboardData(GetWebCustomDataFormatType().ToFormatEtc().cfFormat);
   if (!hdata)
     return;
 
@@ -620,7 +634,7 @@ void Clipboard::ReadCustomData(ClipboardType clipboard_type,
   ::GlobalUnlock(hdata);
 }
 
-void Clipboard::ReadBookmark(base::string16* title, std::string* url) const {
+void ClipboardWin::ReadBookmark(base::string16* title, std::string* url) const {
   if (title)
     title->clear();
 
@@ -632,7 +646,7 @@ void Clipboard::ReadBookmark(base::string16* title, std::string* url) const {
   if (!clipboard.Acquire(GetClipboardWindow()))
     return;
 
-  HANDLE data = ::GetClipboardData(GetUrlWFormatType().ToUINT());
+  HANDLE data = ::GetClipboardData(GetUrlWFormatType().ToFormatEtc().cfFormat);
   if (!data)
     return;
 
@@ -642,7 +656,8 @@ void Clipboard::ReadBookmark(base::string16* title, std::string* url) const {
   ParseBookmarkClipboardFormat(bookmark, title, url);
 }
 
-void Clipboard::ReadData(const FormatType& format, std::string* result) const {
+void ClipboardWin::ReadData(const FormatType& format,
+                            std::string* result) const {
   if (!result) {
     NOTREACHED();
     return;
@@ -652,7 +667,7 @@ void Clipboard::ReadData(const FormatType& format, std::string* result) const {
   if (!clipboard.Acquire(GetClipboardWindow()))
     return;
 
-  HANDLE data = ::GetClipboardData(format.ToUINT());
+  HANDLE data = ::GetClipboardData(format.ToFormatEtc().cfFormat);
   if (!data)
     return;
 
@@ -661,173 +676,180 @@ void Clipboard::ReadData(const FormatType& format, std::string* result) const {
   ::GlobalUnlock(data);
 }
 
-// static
-void Clipboard::ParseBookmarkClipboardFormat(const base::string16& bookmark,
-                                             base::string16* title,
-                                             std::string* url) {
-  const base::string16 kDelim = base::ASCIIToUTF16("\r\n");
+void ClipboardWin::WriteObjects(ClipboardType type, const ObjectMap& objects) {
+  DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
 
-  const size_t title_end = bookmark.find_first_of(kDelim);
-  if (title)
-    title->assign(bookmark.substr(0, title_end));
+  ScopedClipboard clipboard;
+  if (!clipboard.Acquire(GetClipboardWindow()))
+    return;
 
-  if (url) {
-    const size_t url_start = bookmark.find_first_not_of(kDelim, title_end);
-    if (url_start != base::string16::npos) {
-      *url = base::UTF16ToUTF8(
-          bookmark.substr(url_start, base::string16::npos));
-    }
+  ::EmptyClipboard();
+
+  for (ObjectMap::const_iterator iter = objects.begin(); iter != objects.end();
+       ++iter) {
+    DispatchObject(static_cast<ObjectType>(iter->first), iter->second);
   }
 }
 
-// static
-Clipboard::FormatType Clipboard::GetFormatType(
-    const std::string& format_string) {
-  return FormatType(
-      ::RegisterClipboardFormat(base::ASCIIToWide(format_string).c_str()));
-}
+void ClipboardWin::WriteText(const char* text_data, size_t text_len) {
+  base::string16 text;
+  base::UTF8ToUTF16(text_data, text_len, &text);
+  HGLOBAL glob = CreateGlobalData(text);
 
-// static
-const Clipboard::FormatType& Clipboard::GetUrlFormatType() {
-  CR_DEFINE_STATIC_LOCAL(
-      FormatType, type, (::RegisterClipboardFormat(CFSTR_INETURLA)));
-  return type;
+  WriteToClipboard(CF_UNICODETEXT, glob);
 }
 
-// static
-const Clipboard::FormatType& Clipboard::GetUrlWFormatType() {
-  CR_DEFINE_STATIC_LOCAL(
-      FormatType, type, (::RegisterClipboardFormat(CFSTR_INETURLW)));
-  return type;
-}
+void ClipboardWin::WriteHTML(const char* markup_data,
+                             size_t markup_len,
+                             const char* url_data,
+                             size_t url_len) {
+  std::string markup(markup_data, markup_len);
+  std::string url;
 
-// static
-const Clipboard::FormatType& Clipboard::GetMozUrlFormatType() {
-  CR_DEFINE_STATIC_LOCAL(
-      FormatType, type, (::RegisterClipboardFormat(L"text/x-moz-url")));
-  return type;
-}
+  if (url_len > 0)
+    url.assign(url_data, url_len);
 
-// static
-const Clipboard::FormatType& Clipboard::GetPlainTextFormatType() {
-  CR_DEFINE_STATIC_LOCAL(FormatType, type, (CF_TEXT));
-  return type;
-}
+  std::string html_fragment = ClipboardUtil::HtmlToCFHtml(markup, url);
+  HGLOBAL glob = CreateGlobalData(html_fragment);
 
-// static
-const Clipboard::FormatType& Clipboard::GetPlainTextWFormatType() {
-  CR_DEFINE_STATIC_LOCAL(FormatType, type, (CF_UNICODETEXT));
-  return type;
+  WriteToClipboard(Clipboard::GetHtmlFormatType().ToFormatEtc().cfFormat, glob);
 }
 
-// static
-const Clipboard::FormatType& Clipboard::GetFilenameFormatType() {
-  CR_DEFINE_STATIC_LOCAL(
-      FormatType, type, (::RegisterClipboardFormat(CFSTR_FILENAMEA)));
-  return type;
+void ClipboardWin::WriteRTF(const char* rtf_data, size_t data_len) {
+  WriteData(GetRtfFormatType(), rtf_data, data_len);
 }
 
-// static
-const Clipboard::FormatType& Clipboard::GetFilenameWFormatType() {
-  CR_DEFINE_STATIC_LOCAL(
-      FormatType, type, (::RegisterClipboardFormat(CFSTR_FILENAMEW)));
-  return type;
-}
+void ClipboardWin::WriteBookmark(const char* title_data,
+                                 size_t title_len,
+                                 const char* url_data,
+                                 size_t url_len) {
+  std::string bookmark(title_data, title_len);
+  bookmark.append(1, L'\n');
+  bookmark.append(url_data, url_len);
 
-// MS HTML Format
-// static
-const Clipboard::FormatType& Clipboard::GetHtmlFormatType() {
-  CR_DEFINE_STATIC_LOCAL(
-      FormatType, type, (::RegisterClipboardFormat(L"HTML Format")));
-  return type;
-}
+  base::string16 wide_bookmark = base::UTF8ToUTF16(bookmark);
+  HGLOBAL glob = CreateGlobalData(wide_bookmark);
 
-// MS RTF Format
-// static
-const Clipboard::FormatType& Clipboard::GetRtfFormatType() {
-  CR_DEFINE_STATIC_LOCAL(
-      FormatType, type, (::RegisterClipboardFormat(L"Rich Text Format")));
-  return type;
+  WriteToClipboard(GetUrlWFormatType().ToFormatEtc().cfFormat, glob);
 }
 
-// static
-const Clipboard::FormatType& Clipboard::GetBitmapFormatType() {
-  CR_DEFINE_STATIC_LOCAL(FormatType, type, (CF_BITMAP));
-  return type;
+void ClipboardWin::WriteWebSmartPaste() {
+  DCHECK(clipboard_owner_->hwnd() != NULL);
+  ::SetClipboardData(GetWebKitSmartPasteFormatType().ToFormatEtc().cfFormat,
+                     NULL);
 }
 
-// Firefox text/html
-// static
-const Clipboard::FormatType& Clipboard::GetTextHtmlFormatType() {
-  CR_DEFINE_STATIC_LOCAL(
-      FormatType, type, (::RegisterClipboardFormat(L"text/html")));
-  return type;
-}
+void ClipboardWin::WriteBitmap(const SkBitmap& bitmap) {
+  HDC dc = ::GetDC(NULL);
 
-// static
-const Clipboard::FormatType& Clipboard::GetCFHDropFormatType() {
-  CR_DEFINE_STATIC_LOCAL(FormatType, type, (CF_HDROP));
-  return type;
-}
+  // This doesn't actually cost us a memcpy when the bitmap comes from the
+  // renderer as we load it into the bitmap using setPixels which just sets a
+  // pointer.  Someone has to memcpy it into GDI, it might as well be us here.
 
-// static
-const Clipboard::FormatType& Clipboard::GetFileDescriptorFormatType() {
-  CR_DEFINE_STATIC_LOCAL(
-      FormatType, type, (::RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR)));
-  return type;
-}
+  // TODO(darin): share data in gfx/bitmap_header.cc somehow
+  BITMAPINFO bm_info = {0};
+  bm_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+  bm_info.bmiHeader.biWidth = bitmap.width();
+  bm_info.bmiHeader.biHeight = -bitmap.height();  // sets vertical orientation
+  bm_info.bmiHeader.biPlanes = 1;
+  bm_info.bmiHeader.biBitCount = 32;
+  bm_info.bmiHeader.biCompression = BI_RGB;
 
-// static
-const Clipboard::FormatType& Clipboard::GetFileContentZeroFormatType() {
-  CR_DEFINE_STATIC_LOCAL(
-      FormatType, type, (::RegisterClipboardFormat(CFSTR_FILECONTENTS), 0));
-  return type;
-}
+  // ::CreateDIBSection allocates memory for us to copy our bitmap into.
+  // Unfortunately, we can't write the created bitmap to the clipboard,
+  // (see http://msdn2.microsoft.com/en-us/library/ms532292.aspx)
+  void* bits;
+  HBITMAP source_hbitmap =
+      ::CreateDIBSection(dc, &bm_info, DIB_RGB_COLORS, &bits, NULL, 0);
 
-// static
-const Clipboard::FormatType& Clipboard::GetIDListFormatType() {
-  CR_DEFINE_STATIC_LOCAL(
-      FormatType, type, (::RegisterClipboardFormat(CFSTR_SHELLIDLIST)));
-  return type;
-}
+  if (bits && source_hbitmap) {
+    {
+      SkAutoLockPixels bitmap_lock(bitmap);
+      // Copy the bitmap out of shared memory and into GDI
+      memcpy(bits, bitmap.getPixels(), bitmap.getSize());
+    }
 
-// static
-const Clipboard::FormatType& Clipboard::GetWebKitSmartPasteFormatType() {
-  CR_DEFINE_STATIC_LOCAL(
-      FormatType,
-      type,
-      (::RegisterClipboardFormat(L"WebKit Smart Paste Format")));
-  return type;
+    // Now we have an HBITMAP, we can write it to the clipboard
+    WriteBitmapFromHandle(source_hbitmap,
+                          gfx::Size(bitmap.width(), bitmap.height()));
+  }
+
+  ::DeleteObject(source_hbitmap);
+  ::ReleaseDC(NULL, dc);
 }
 
-// static
-const Clipboard::FormatType& Clipboard::GetWebCustomDataFormatType() {
-  // TODO(dcheng): This name is temporary. See http://crbug.com/106449.
-  CR_DEFINE_STATIC_LOCAL(
-      FormatType,
-      type,
-      (::RegisterClipboardFormat(L"Chromium Web Custom MIME Data Format")));
-  return type;
+void ClipboardWin::WriteData(const FormatType& format,
+                             const char* data_data,
+                             size_t data_len) {
+  HGLOBAL hdata = ::GlobalAlloc(GMEM_MOVEABLE, data_len);
+  if (!hdata)
+    return;
+
+  char* data = static_cast<char*>(::GlobalLock(hdata));
+  memcpy(data, data_data, data_len);
+  ::GlobalUnlock(data);
+  WriteToClipboard(format.ToFormatEtc().cfFormat, hdata);
 }
 
-// static
-const Clipboard::FormatType& Clipboard::GetPepperCustomDataFormatType() {
-  CR_DEFINE_STATIC_LOCAL(
-      FormatType,
-      type,
-      (::RegisterClipboardFormat(L"Chromium Pepper MIME Data Format")));
-  return type;
+void ClipboardWin::WriteBitmapFromHandle(HBITMAP source_hbitmap,
+                                         const gfx::Size& size) {
+  // We would like to just call ::SetClipboardData on the source_hbitmap,
+  // but that bitmap might not be of a sort we can write to the clipboard.
+  // For this reason, we create a new bitmap, copy the bits over, and then
+  // write that to the clipboard.
+
+  HDC dc = ::GetDC(NULL);
+  HDC compatible_dc = ::CreateCompatibleDC(NULL);
+  HDC source_dc = ::CreateCompatibleDC(NULL);
+
+  // This is the HBITMAP we will eventually write to the clipboard
+  HBITMAP hbitmap = ::CreateCompatibleBitmap(dc, size.width(), size.height());
+  if (!hbitmap) {
+    // Failed to create the bitmap
+    ::DeleteDC(compatible_dc);
+    ::DeleteDC(source_dc);
+    ::ReleaseDC(NULL, dc);
+    return;
+  }
+
+  HBITMAP old_hbitmap = (HBITMAP)SelectObject(compatible_dc, hbitmap);
+  HBITMAP old_source = (HBITMAP)SelectObject(source_dc, source_hbitmap);
+
+  // Now we need to blend it into an HBITMAP we can place on the clipboard
+  BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA};
+  ::GdiAlphaBlend(compatible_dc,
+                  0,
+                  0,
+                  size.width(),
+                  size.height(),
+                  source_dc,
+                  0,
+                  0,
+                  size.width(),
+                  size.height(),
+                  bf);
+
+  // Clean up all the handles we just opened
+  ::SelectObject(compatible_dc, old_hbitmap);
+  ::SelectObject(source_dc, old_source);
+  ::DeleteObject(old_hbitmap);
+  ::DeleteObject(old_source);
+  ::DeleteDC(compatible_dc);
+  ::DeleteDC(source_dc);
+  ::ReleaseDC(NULL, dc);
+
+  WriteToClipboard(CF_BITMAP, hbitmap);
 }
 
-// static
-void Clipboard::FreeData(unsigned int format, HANDLE data) {
-  if (format == CF_BITMAP)
-    ::DeleteObject(static_cast<HBITMAP>(data));
-  else
-    ::GlobalFree(data);
+void ClipboardWin::WriteToClipboard(unsigned int format, HANDLE handle) {
+  DCHECK(clipboard_owner_->hwnd() != NULL);
+  if (handle && !::SetClipboardData(format, handle)) {
+    DCHECK(ERROR_CLIPBOARD_NOT_OPEN != GetLastError());
+    FreeData(format, handle);
+  }
 }
 
-HWND Clipboard::GetClipboardWindow() const {
+HWND ClipboardWin::GetClipboardWindow() const {
   if (!clipboard_owner_)
     return NULL;