Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / ui / base / clipboard / clipboard_win.cc
blob36d042d7abc409856a5036a93d99d20147caaf05
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // Many of these functions are based on those found in
6 // webkit/port/platform/PasteboardWin.cpp
8 #include "ui/base/clipboard/clipboard.h"
10 #include <shellapi.h>
11 #include <shlobj.h>
13 #include "base/basictypes.h"
14 #include "base/bind.h"
15 #include "base/files/file_path.h"
16 #include "base/logging.h"
17 #include "base/memory/shared_memory.h"
18 #include "base/message_loop/message_loop.h"
19 #include "base/numerics/safe_conversions.h"
20 #include "base/stl_util.h"
21 #include "base/strings/string_number_conversions.h"
22 #include "base/strings/string_util.h"
23 #include "base/strings/utf_offset_string_conversions.h"
24 #include "base/strings/utf_string_conversions.h"
25 #include "base/win/message_window.h"
26 #include "base/win/scoped_gdi_object.h"
27 #include "base/win/scoped_hdc.h"
28 #include "third_party/skia/include/core/SkBitmap.h"
29 #include "ui/base/clipboard/clipboard_util_win.h"
30 #include "ui/base/clipboard/custom_data_helper.h"
31 #include "ui/gfx/canvas.h"
32 #include "ui/gfx/size.h"
34 namespace ui {
36 namespace {
38 // A scoper to manage acquiring and automatically releasing the clipboard.
39 class ScopedClipboard {
40 public:
41 ScopedClipboard() : opened_(false) { }
43 ~ScopedClipboard() {
44 if (opened_)
45 Release();
48 bool Acquire(HWND owner) {
49 const int kMaxAttemptsToOpenClipboard = 5;
51 if (opened_) {
52 NOTREACHED();
53 return false;
56 // Attempt to open the clipboard, which will acquire the Windows clipboard
57 // lock. This may fail if another process currently holds this lock.
58 // We're willing to try a few times in the hopes of acquiring it.
60 // This turns out to be an issue when using remote desktop because the
61 // rdpclip.exe process likes to read what we've written to the clipboard and
62 // send it to the RDP client. If we open and close the clipboard in quick
63 // succession, we might be trying to open it while rdpclip.exe has it open,
64 // See Bug 815425.
66 // In fact, we believe we'll only spin this loop over remote desktop. In
67 // normal situations, the user is initiating clipboard operations and there
68 // shouldn't be contention.
70 for (int attempts = 0; attempts < kMaxAttemptsToOpenClipboard; ++attempts) {
71 // If we didn't manage to open the clipboard, sleep a bit and be hopeful.
72 if (attempts != 0)
73 ::Sleep(5);
75 if (::OpenClipboard(owner)) {
76 opened_ = true;
77 return true;
81 // We failed to acquire the clipboard.
82 return false;
85 void Release() {
86 if (opened_) {
87 ::CloseClipboard();
88 opened_ = false;
89 } else {
90 NOTREACHED();
94 private:
95 bool opened_;
98 bool ClipboardOwnerWndProc(UINT message,
99 WPARAM wparam,
100 LPARAM lparam,
101 LRESULT* result) {
102 switch (message) {
103 case WM_RENDERFORMAT:
104 // This message comes when SetClipboardData was sent a null data handle
105 // and now it's come time to put the data on the clipboard.
106 // We always set data, so there isn't a need to actually do anything here.
107 break;
108 case WM_RENDERALLFORMATS:
109 // This message comes when SetClipboardData was sent a null data handle
110 // and now this application is about to quit, so it must put data on
111 // the clipboard before it exits.
112 // We always set data, so there isn't a need to actually do anything here.
113 break;
114 case WM_DRAWCLIPBOARD:
115 break;
116 case WM_DESTROY:
117 break;
118 case WM_CHANGECBCHAIN:
119 break;
120 default:
121 return false;
124 *result = 0;
125 return true;
128 template <typename charT>
129 HGLOBAL CreateGlobalData(const std::basic_string<charT>& str) {
130 HGLOBAL data =
131 ::GlobalAlloc(GMEM_MOVEABLE, ((str.size() + 1) * sizeof(charT)));
132 if (data) {
133 charT* raw_data = static_cast<charT*>(::GlobalLock(data));
134 memcpy(raw_data, str.data(), str.size() * sizeof(charT));
135 raw_data[str.size()] = '\0';
136 ::GlobalUnlock(data);
138 return data;
141 bool BitmapHasInvalidPremultipliedColors(const SkBitmap& bitmap) {
142 for (int x = 0; x < bitmap.width(); ++x) {
143 for (int y = 0; y < bitmap.height(); ++y) {
144 uint32_t pixel = *bitmap.getAddr32(x, y);
145 if (SkColorGetR(pixel) > SkColorGetA(pixel) ||
146 SkColorGetG(pixel) > SkColorGetA(pixel) ||
147 SkColorGetB(pixel) > SkColorGetA(pixel))
148 return true;
151 return false;
154 void MakeBitmapOpaque(const SkBitmap& bitmap) {
155 for (int x = 0; x < bitmap.width(); ++x) {
156 for (int y = 0; y < bitmap.height(); ++y) {
157 *bitmap.getAddr32(x, y) = SkColorSetA(*bitmap.getAddr32(x, y), 0xFF);
162 } // namespace
164 Clipboard::FormatType::FormatType() : data_() {}
166 Clipboard::FormatType::FormatType(UINT native_format) : data_() {
167 // There's no good way to actually initialize this in the constructor in
168 // C++03.
169 data_.cfFormat = native_format;
170 data_.dwAspect = DVASPECT_CONTENT;
171 data_.lindex = -1;
172 data_.tymed = TYMED_HGLOBAL;
175 Clipboard::FormatType::FormatType(UINT native_format, LONG index) : data_() {
176 // There's no good way to actually initialize this in the constructor in
177 // C++03.
178 data_.cfFormat = native_format;
179 data_.dwAspect = DVASPECT_CONTENT;
180 data_.lindex = index;
181 data_.tymed = TYMED_HGLOBAL;
184 Clipboard::FormatType::~FormatType() {
187 std::string Clipboard::FormatType::Serialize() const {
188 return base::IntToString(data_.cfFormat);
191 // static
192 Clipboard::FormatType Clipboard::FormatType::Deserialize(
193 const std::string& serialization) {
194 int clipboard_format = -1;
195 if (!base::StringToInt(serialization, &clipboard_format)) {
196 NOTREACHED();
197 return FormatType();
199 return FormatType(clipboard_format);
202 bool Clipboard::FormatType::operator<(const FormatType& other) const {
203 return ToUINT() < other.ToUINT();
206 bool Clipboard::FormatType::Equals(const FormatType& other) const {
207 return ToUINT() == other.ToUINT();
210 Clipboard::Clipboard() {
211 if (base::MessageLoopForUI::IsCurrent())
212 clipboard_owner_.reset(new base::win::MessageWindow());
215 Clipboard::~Clipboard() {
218 void Clipboard::WriteObjects(ClipboardType type, const ObjectMap& objects) {
219 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
221 ScopedClipboard clipboard;
222 if (!clipboard.Acquire(GetClipboardWindow()))
223 return;
225 ::EmptyClipboard();
227 for (ObjectMap::const_iterator iter = objects.begin();
228 iter != objects.end(); ++iter) {
229 DispatchObject(static_cast<ObjectType>(iter->first), iter->second);
233 void Clipboard::WriteText(const char* text_data, size_t text_len) {
234 base::string16 text;
235 base::UTF8ToUTF16(text_data, text_len, &text);
236 HGLOBAL glob = CreateGlobalData(text);
238 WriteToClipboard(CF_UNICODETEXT, glob);
241 void Clipboard::WriteHTML(const char* markup_data,
242 size_t markup_len,
243 const char* url_data,
244 size_t url_len) {
245 std::string markup(markup_data, markup_len);
246 std::string url;
248 if (url_len > 0)
249 url.assign(url_data, url_len);
251 std::string html_fragment = ClipboardUtil::HtmlToCFHtml(markup, url);
252 HGLOBAL glob = CreateGlobalData(html_fragment);
254 WriteToClipboard(Clipboard::GetHtmlFormatType().ToUINT(), glob);
257 void Clipboard::WriteRTF(const char* rtf_data, size_t data_len) {
258 WriteData(GetRtfFormatType(), rtf_data, data_len);
261 void Clipboard::WriteBookmark(const char* title_data,
262 size_t title_len,
263 const char* url_data,
264 size_t url_len) {
265 std::string bookmark(title_data, title_len);
266 bookmark.append(1, L'\n');
267 bookmark.append(url_data, url_len);
269 base::string16 wide_bookmark = base::UTF8ToWide(bookmark);
270 HGLOBAL glob = CreateGlobalData(wide_bookmark);
272 WriteToClipboard(GetUrlWFormatType().ToUINT(), glob);
275 void Clipboard::WriteWebSmartPaste() {
276 DCHECK(clipboard_owner_->hwnd() != NULL);
277 ::SetClipboardData(GetWebKitSmartPasteFormatType().ToUINT(), NULL);
280 void Clipboard::WriteBitmap(const SkBitmap& bitmap) {
281 HDC dc = ::GetDC(NULL);
283 // This doesn't actually cost us a memcpy when the bitmap comes from the
284 // renderer as we load it into the bitmap using setPixels which just sets a
285 // pointer. Someone has to memcpy it into GDI, it might as well be us here.
287 // TODO(darin): share data in gfx/bitmap_header.cc somehow
288 BITMAPINFO bm_info = {0};
289 bm_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
290 bm_info.bmiHeader.biWidth = bitmap.width();
291 bm_info.bmiHeader.biHeight = -bitmap.height(); // sets vertical orientation
292 bm_info.bmiHeader.biPlanes = 1;
293 bm_info.bmiHeader.biBitCount = 32;
294 bm_info.bmiHeader.biCompression = BI_RGB;
296 // ::CreateDIBSection allocates memory for us to copy our bitmap into.
297 // Unfortunately, we can't write the created bitmap to the clipboard,
298 // (see http://msdn2.microsoft.com/en-us/library/ms532292.aspx)
299 void *bits;
300 HBITMAP source_hbitmap =
301 ::CreateDIBSection(dc, &bm_info, DIB_RGB_COLORS, &bits, NULL, 0);
303 if (bits && source_hbitmap) {
305 SkAutoLockPixels bitmap_lock(bitmap);
306 // Copy the bitmap out of shared memory and into GDI
307 memcpy(bits, bitmap.getPixels(), bitmap.getSize());
310 // Now we have an HBITMAP, we can write it to the clipboard
311 WriteBitmapFromHandle(source_hbitmap,
312 gfx::Size(bitmap.width(), bitmap.height()));
315 ::DeleteObject(source_hbitmap);
316 ::ReleaseDC(NULL, dc);
319 void Clipboard::WriteBitmapFromHandle(HBITMAP source_hbitmap,
320 const gfx::Size& size) {
321 // We would like to just call ::SetClipboardData on the source_hbitmap,
322 // but that bitmap might not be of a sort we can write to the clipboard.
323 // For this reason, we create a new bitmap, copy the bits over, and then
324 // write that to the clipboard.
326 HDC dc = ::GetDC(NULL);
327 HDC compatible_dc = ::CreateCompatibleDC(NULL);
328 HDC source_dc = ::CreateCompatibleDC(NULL);
330 // This is the HBITMAP we will eventually write to the clipboard
331 HBITMAP hbitmap = ::CreateCompatibleBitmap(dc, size.width(), size.height());
332 if (!hbitmap) {
333 // Failed to create the bitmap
334 ::DeleteDC(compatible_dc);
335 ::DeleteDC(source_dc);
336 ::ReleaseDC(NULL, dc);
337 return;
340 HBITMAP old_hbitmap = (HBITMAP)SelectObject(compatible_dc, hbitmap);
341 HBITMAP old_source = (HBITMAP)SelectObject(source_dc, source_hbitmap);
343 // Now we need to blend it into an HBITMAP we can place on the clipboard
344 BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA};
345 ::GdiAlphaBlend(compatible_dc, 0, 0, size.width(), size.height(),
346 source_dc, 0, 0, size.width(), size.height(), bf);
348 // Clean up all the handles we just opened
349 ::SelectObject(compatible_dc, old_hbitmap);
350 ::SelectObject(source_dc, old_source);
351 ::DeleteObject(old_hbitmap);
352 ::DeleteObject(old_source);
353 ::DeleteDC(compatible_dc);
354 ::DeleteDC(source_dc);
355 ::ReleaseDC(NULL, dc);
357 WriteToClipboard(CF_BITMAP, hbitmap);
360 void Clipboard::WriteData(const FormatType& format,
361 const char* data_data,
362 size_t data_len) {
363 HGLOBAL hdata = ::GlobalAlloc(GMEM_MOVEABLE, data_len);
364 if (!hdata)
365 return;
367 char* data = static_cast<char*>(::GlobalLock(hdata));
368 memcpy(data, data_data, data_len);
369 ::GlobalUnlock(data);
370 WriteToClipboard(format.ToUINT(), hdata);
373 void Clipboard::WriteToClipboard(unsigned int format, HANDLE handle) {
374 DCHECK(clipboard_owner_->hwnd() != NULL);
375 if (handle && !::SetClipboardData(format, handle)) {
376 DCHECK(ERROR_CLIPBOARD_NOT_OPEN != GetLastError());
377 FreeData(format, handle);
381 uint64 Clipboard::GetSequenceNumber(ClipboardType type) {
382 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
383 return ::GetClipboardSequenceNumber();
386 bool Clipboard::IsFormatAvailable(const Clipboard::FormatType& format,
387 ClipboardType type) const {
388 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
389 return ::IsClipboardFormatAvailable(format.ToUINT()) != FALSE;
392 void Clipboard::Clear(ClipboardType type) {
393 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
394 ScopedClipboard clipboard;
395 if (!clipboard.Acquire(GetClipboardWindow()))
396 return;
398 ::EmptyClipboard();
401 void Clipboard::ReadAvailableTypes(ClipboardType type,
402 std::vector<base::string16>* types,
403 bool* contains_filenames) const {
404 if (!types || !contains_filenames) {
405 NOTREACHED();
406 return;
409 types->clear();
410 if (::IsClipboardFormatAvailable(GetPlainTextFormatType().ToUINT()))
411 types->push_back(base::UTF8ToUTF16(kMimeTypeText));
412 if (::IsClipboardFormatAvailable(GetHtmlFormatType().ToUINT()))
413 types->push_back(base::UTF8ToUTF16(kMimeTypeHTML));
414 if (::IsClipboardFormatAvailable(GetRtfFormatType().ToUINT()))
415 types->push_back(base::UTF8ToUTF16(kMimeTypeRTF));
416 if (::IsClipboardFormatAvailable(CF_DIB))
417 types->push_back(base::UTF8ToUTF16(kMimeTypePNG));
418 *contains_filenames = false;
420 // Acquire the clipboard.
421 ScopedClipboard clipboard;
422 if (!clipboard.Acquire(GetClipboardWindow()))
423 return;
425 HANDLE hdata = ::GetClipboardData(GetWebCustomDataFormatType().ToUINT());
426 if (!hdata)
427 return;
429 ReadCustomDataTypes(::GlobalLock(hdata), ::GlobalSize(hdata), types);
430 ::GlobalUnlock(hdata);
433 void Clipboard::ReadText(ClipboardType type, base::string16* result) const {
434 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
435 if (!result) {
436 NOTREACHED();
437 return;
440 result->clear();
442 // Acquire the clipboard.
443 ScopedClipboard clipboard;
444 if (!clipboard.Acquire(GetClipboardWindow()))
445 return;
447 HANDLE data = ::GetClipboardData(CF_UNICODETEXT);
448 if (!data)
449 return;
451 result->assign(static_cast<const base::char16*>(::GlobalLock(data)));
452 ::GlobalUnlock(data);
455 void Clipboard::ReadAsciiText(ClipboardType type, std::string* result) const {
456 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
457 if (!result) {
458 NOTREACHED();
459 return;
462 result->clear();
464 // Acquire the clipboard.
465 ScopedClipboard clipboard;
466 if (!clipboard.Acquire(GetClipboardWindow()))
467 return;
469 HANDLE data = ::GetClipboardData(CF_TEXT);
470 if (!data)
471 return;
473 result->assign(static_cast<const char*>(::GlobalLock(data)));
474 ::GlobalUnlock(data);
477 void Clipboard::ReadHTML(ClipboardType type,
478 base::string16* markup,
479 std::string* src_url,
480 uint32* fragment_start,
481 uint32* fragment_end) const {
482 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
484 markup->clear();
485 // TODO(dcheng): Remove these checks, I don't think they should be optional.
486 DCHECK(src_url);
487 if (src_url)
488 src_url->clear();
489 *fragment_start = 0;
490 *fragment_end = 0;
492 // Acquire the clipboard.
493 ScopedClipboard clipboard;
494 if (!clipboard.Acquire(GetClipboardWindow()))
495 return;
497 HANDLE data = ::GetClipboardData(GetHtmlFormatType().ToUINT());
498 if (!data)
499 return;
501 std::string cf_html(static_cast<const char*>(::GlobalLock(data)));
502 ::GlobalUnlock(data);
504 size_t html_start = std::string::npos;
505 size_t start_index = std::string::npos;
506 size_t end_index = std::string::npos;
507 ClipboardUtil::CFHtmlExtractMetadata(cf_html, src_url, &html_start,
508 &start_index, &end_index);
510 // This might happen if the contents of the clipboard changed and CF_HTML is
511 // no longer available.
512 if (start_index == std::string::npos ||
513 end_index == std::string::npos ||
514 html_start == std::string::npos)
515 return;
517 if (start_index < html_start || end_index < start_index)
518 return;
520 std::vector<size_t> offsets;
521 offsets.push_back(start_index - html_start);
522 offsets.push_back(end_index - html_start);
523 markup->assign(base::UTF8ToUTF16AndAdjustOffsets(cf_html.data() + html_start,
524 &offsets));
525 *fragment_start = base::checked_cast<uint32>(offsets[0]);
526 *fragment_end = base::checked_cast<uint32>(offsets[1]);
529 void Clipboard::ReadRTF(ClipboardType type, std::string* result) const {
530 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
532 ReadData(GetRtfFormatType(), result);
535 SkBitmap Clipboard::ReadImage(ClipboardType type) const {
536 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
538 // Acquire the clipboard.
539 ScopedClipboard clipboard;
540 if (!clipboard.Acquire(GetClipboardWindow()))
541 return SkBitmap();
543 // We use a DIB rather than a DDB here since ::GetObject() with the
544 // HBITMAP returned from ::GetClipboardData(CF_BITMAP) always reports a color
545 // depth of 32bpp.
546 BITMAPINFO* bitmap = static_cast<BITMAPINFO*>(::GetClipboardData(CF_DIB));
547 if (!bitmap)
548 return SkBitmap();
549 int color_table_length = 0;
550 switch (bitmap->bmiHeader.biBitCount) {
551 case 1:
552 case 4:
553 case 8:
554 color_table_length = bitmap->bmiHeader.biClrUsed
555 ? bitmap->bmiHeader.biClrUsed
556 : 1 << bitmap->bmiHeader.biBitCount;
557 break;
558 case 16:
559 case 32:
560 if (bitmap->bmiHeader.biCompression == BI_BITFIELDS)
561 color_table_length = 3;
562 break;
563 case 24:
564 break;
565 default:
566 NOTREACHED();
568 const void* bitmap_bits = reinterpret_cast<const char*>(bitmap)
569 + bitmap->bmiHeader.biSize + color_table_length * sizeof(RGBQUAD);
571 gfx::Canvas canvas(gfx::Size(bitmap->bmiHeader.biWidth,
572 bitmap->bmiHeader.biHeight),
573 1.0f,
574 false);
576 skia::ScopedPlatformPaint scoped_platform_paint(canvas.sk_canvas());
577 HDC dc = scoped_platform_paint.GetPlatformSurface();
578 ::SetDIBitsToDevice(dc, 0, 0, bitmap->bmiHeader.biWidth,
579 bitmap->bmiHeader.biHeight, 0, 0, 0,
580 bitmap->bmiHeader.biHeight, bitmap_bits, bitmap,
581 DIB_RGB_COLORS);
583 // Windows doesn't really handle alpha channels well in many situations. When
584 // the source image is < 32 bpp, we force the bitmap to be opaque. When the
585 // source image is 32 bpp, the alpha channel might still contain garbage data.
586 // Since Windows uses premultiplied alpha, we scan for instances where
587 // (R, G, B) > A. If there are any invalid premultiplied colors in the image,
588 // we assume the alpha channel contains garbage and force the bitmap to be
589 // opaque as well. Note that this heuristic will fail on a transparent bitmap
590 // containing only black pixels...
591 const SkBitmap& device_bitmap =
592 canvas.sk_canvas()->getDevice()->accessBitmap(true);
594 SkAutoLockPixels lock(device_bitmap);
595 bool has_invalid_alpha_channel = bitmap->bmiHeader.biBitCount < 32 ||
596 BitmapHasInvalidPremultipliedColors(device_bitmap);
597 if (has_invalid_alpha_channel) {
598 MakeBitmapOpaque(device_bitmap);
602 return canvas.ExtractImageRep().sk_bitmap();
605 void Clipboard::ReadCustomData(ClipboardType clipboard_type,
606 const base::string16& type,
607 base::string16* result) const {
608 DCHECK_EQ(clipboard_type, CLIPBOARD_TYPE_COPY_PASTE);
610 // Acquire the clipboard.
611 ScopedClipboard clipboard;
612 if (!clipboard.Acquire(GetClipboardWindow()))
613 return;
615 HANDLE hdata = ::GetClipboardData(GetWebCustomDataFormatType().ToUINT());
616 if (!hdata)
617 return;
619 ReadCustomDataForType(::GlobalLock(hdata), ::GlobalSize(hdata), type, result);
620 ::GlobalUnlock(hdata);
623 void Clipboard::ReadBookmark(base::string16* title, std::string* url) const {
624 if (title)
625 title->clear();
627 if (url)
628 url->clear();
630 // Acquire the clipboard.
631 ScopedClipboard clipboard;
632 if (!clipboard.Acquire(GetClipboardWindow()))
633 return;
635 HANDLE data = ::GetClipboardData(GetUrlWFormatType().ToUINT());
636 if (!data)
637 return;
639 base::string16 bookmark(static_cast<const base::char16*>(::GlobalLock(data)));
640 ::GlobalUnlock(data);
642 ParseBookmarkClipboardFormat(bookmark, title, url);
645 void Clipboard::ReadData(const FormatType& format, std::string* result) const {
646 if (!result) {
647 NOTREACHED();
648 return;
651 ScopedClipboard clipboard;
652 if (!clipboard.Acquire(GetClipboardWindow()))
653 return;
655 HANDLE data = ::GetClipboardData(format.ToUINT());
656 if (!data)
657 return;
659 result->assign(static_cast<const char*>(::GlobalLock(data)),
660 ::GlobalSize(data));
661 ::GlobalUnlock(data);
664 // static
665 void Clipboard::ParseBookmarkClipboardFormat(const base::string16& bookmark,
666 base::string16* title,
667 std::string* url) {
668 const base::string16 kDelim = base::ASCIIToUTF16("\r\n");
670 const size_t title_end = bookmark.find_first_of(kDelim);
671 if (title)
672 title->assign(bookmark.substr(0, title_end));
674 if (url) {
675 const size_t url_start = bookmark.find_first_not_of(kDelim, title_end);
676 if (url_start != base::string16::npos) {
677 *url = base::UTF16ToUTF8(
678 bookmark.substr(url_start, base::string16::npos));
683 // static
684 Clipboard::FormatType Clipboard::GetFormatType(
685 const std::string& format_string) {
686 return FormatType(
687 ::RegisterClipboardFormat(base::ASCIIToWide(format_string).c_str()));
690 // static
691 const Clipboard::FormatType& Clipboard::GetUrlFormatType() {
692 CR_DEFINE_STATIC_LOCAL(
693 FormatType, type, (::RegisterClipboardFormat(CFSTR_INETURLA)));
694 return type;
697 // static
698 const Clipboard::FormatType& Clipboard::GetUrlWFormatType() {
699 CR_DEFINE_STATIC_LOCAL(
700 FormatType, type, (::RegisterClipboardFormat(CFSTR_INETURLW)));
701 return type;
704 // static
705 const Clipboard::FormatType& Clipboard::GetMozUrlFormatType() {
706 CR_DEFINE_STATIC_LOCAL(
707 FormatType, type, (::RegisterClipboardFormat(L"text/x-moz-url")));
708 return type;
711 // static
712 const Clipboard::FormatType& Clipboard::GetPlainTextFormatType() {
713 CR_DEFINE_STATIC_LOCAL(FormatType, type, (CF_TEXT));
714 return type;
717 // static
718 const Clipboard::FormatType& Clipboard::GetPlainTextWFormatType() {
719 CR_DEFINE_STATIC_LOCAL(FormatType, type, (CF_UNICODETEXT));
720 return type;
723 // static
724 const Clipboard::FormatType& Clipboard::GetFilenameFormatType() {
725 CR_DEFINE_STATIC_LOCAL(
726 FormatType, type, (::RegisterClipboardFormat(CFSTR_FILENAMEA)));
727 return type;
730 // static
731 const Clipboard::FormatType& Clipboard::GetFilenameWFormatType() {
732 CR_DEFINE_STATIC_LOCAL(
733 FormatType, type, (::RegisterClipboardFormat(CFSTR_FILENAMEW)));
734 return type;
737 // MS HTML Format
738 // static
739 const Clipboard::FormatType& Clipboard::GetHtmlFormatType() {
740 CR_DEFINE_STATIC_LOCAL(
741 FormatType, type, (::RegisterClipboardFormat(L"HTML Format")));
742 return type;
745 // MS RTF Format
746 // static
747 const Clipboard::FormatType& Clipboard::GetRtfFormatType() {
748 CR_DEFINE_STATIC_LOCAL(
749 FormatType, type, (::RegisterClipboardFormat(L"Rich Text Format")));
750 return type;
753 // static
754 const Clipboard::FormatType& Clipboard::GetBitmapFormatType() {
755 CR_DEFINE_STATIC_LOCAL(FormatType, type, (CF_BITMAP));
756 return type;
759 // Firefox text/html
760 // static
761 const Clipboard::FormatType& Clipboard::GetTextHtmlFormatType() {
762 CR_DEFINE_STATIC_LOCAL(
763 FormatType, type, (::RegisterClipboardFormat(L"text/html")));
764 return type;
767 // static
768 const Clipboard::FormatType& Clipboard::GetCFHDropFormatType() {
769 CR_DEFINE_STATIC_LOCAL(FormatType, type, (CF_HDROP));
770 return type;
773 // static
774 const Clipboard::FormatType& Clipboard::GetFileDescriptorFormatType() {
775 CR_DEFINE_STATIC_LOCAL(
776 FormatType, type, (::RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR)));
777 return type;
780 // static
781 const Clipboard::FormatType& Clipboard::GetFileContentZeroFormatType() {
782 CR_DEFINE_STATIC_LOCAL(
783 FormatType, type, (::RegisterClipboardFormat(CFSTR_FILECONTENTS), 0));
784 return type;
787 // static
788 const Clipboard::FormatType& Clipboard::GetIDListFormatType() {
789 CR_DEFINE_STATIC_LOCAL(
790 FormatType, type, (::RegisterClipboardFormat(CFSTR_SHELLIDLIST)));
791 return type;
794 // static
795 const Clipboard::FormatType& Clipboard::GetWebKitSmartPasteFormatType() {
796 CR_DEFINE_STATIC_LOCAL(
797 FormatType,
798 type,
799 (::RegisterClipboardFormat(L"WebKit Smart Paste Format")));
800 return type;
803 // static
804 const Clipboard::FormatType& Clipboard::GetWebCustomDataFormatType() {
805 // TODO(dcheng): This name is temporary. See http://crbug.com/106449.
806 CR_DEFINE_STATIC_LOCAL(
807 FormatType,
808 type,
809 (::RegisterClipboardFormat(L"Chromium Web Custom MIME Data Format")));
810 return type;
813 // static
814 const Clipboard::FormatType& Clipboard::GetPepperCustomDataFormatType() {
815 CR_DEFINE_STATIC_LOCAL(
816 FormatType,
817 type,
818 (::RegisterClipboardFormat(L"Chromium Pepper MIME Data Format")));
819 return type;
822 // static
823 void Clipboard::FreeData(unsigned int format, HANDLE data) {
824 if (format == CF_BITMAP)
825 ::DeleteObject(static_cast<HBITMAP>(data));
826 else
827 ::GlobalFree(data);
830 HWND Clipboard::GetClipboardWindow() const {
831 if (!clipboard_owner_)
832 return NULL;
834 if (clipboard_owner_->hwnd() == NULL)
835 clipboard_owner_->Create(base::Bind(&ClipboardOwnerWndProc));
837 return clipboard_owner_->hwnd();
840 } // namespace ui