Remove support for specifying version on command line.
[chromium-blink-merge.git] / ui / base / clipboard / clipboard_win.cc
blob829b1c2b46acd338f501700a0d5512831bca3563
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 <shlobj.h>
11 #include <shellapi.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/safe_numerics.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 Clipboard::Clipboard() {
207 if (base::MessageLoop::current()->type() == base::MessageLoop::TYPE_UI)
208 clipboard_owner_.reset(new base::win::MessageWindow());
211 Clipboard::~Clipboard() {
214 void Clipboard::WriteObjects(ClipboardType type, const ObjectMap& objects) {
215 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
217 ScopedClipboard clipboard;
218 if (!clipboard.Acquire(GetClipboardWindow()))
219 return;
221 ::EmptyClipboard();
223 for (ObjectMap::const_iterator iter = objects.begin();
224 iter != objects.end(); ++iter) {
225 DispatchObject(static_cast<ObjectType>(iter->first), iter->second);
229 void Clipboard::WriteText(const char* text_data, size_t text_len) {
230 base::string16 text;
231 base::UTF8ToUTF16(text_data, text_len, &text);
232 HGLOBAL glob = CreateGlobalData(text);
234 WriteToClipboard(CF_UNICODETEXT, glob);
237 void Clipboard::WriteHTML(const char* markup_data,
238 size_t markup_len,
239 const char* url_data,
240 size_t url_len) {
241 std::string markup(markup_data, markup_len);
242 std::string url;
244 if (url_len > 0)
245 url.assign(url_data, url_len);
247 std::string html_fragment = ClipboardUtil::HtmlToCFHtml(markup, url);
248 HGLOBAL glob = CreateGlobalData(html_fragment);
250 WriteToClipboard(Clipboard::GetHtmlFormatType().ToUINT(), glob);
253 void Clipboard::WriteRTF(const char* rtf_data, size_t data_len) {
254 WriteData(GetRtfFormatType(), rtf_data, data_len);
257 void Clipboard::WriteBookmark(const char* title_data,
258 size_t title_len,
259 const char* url_data,
260 size_t url_len) {
261 std::string bookmark(title_data, title_len);
262 bookmark.append(1, L'\n');
263 bookmark.append(url_data, url_len);
265 base::string16 wide_bookmark = base::UTF8ToWide(bookmark);
266 HGLOBAL glob = CreateGlobalData(wide_bookmark);
268 WriteToClipboard(GetUrlWFormatType().ToUINT(), glob);
271 void Clipboard::WriteWebSmartPaste() {
272 DCHECK(clipboard_owner_->hwnd() != NULL);
273 ::SetClipboardData(GetWebKitSmartPasteFormatType().ToUINT(), NULL);
276 void Clipboard::WriteBitmap(const SkBitmap& bitmap) {
277 HDC dc = ::GetDC(NULL);
279 // This doesn't actually cost us a memcpy when the bitmap comes from the
280 // renderer as we load it into the bitmap using setPixels which just sets a
281 // pointer. Someone has to memcpy it into GDI, it might as well be us here.
283 // TODO(darin): share data in gfx/bitmap_header.cc somehow
284 BITMAPINFO bm_info = {0};
285 bm_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
286 bm_info.bmiHeader.biWidth = bitmap.width();
287 bm_info.bmiHeader.biHeight = -bitmap.height(); // sets vertical orientation
288 bm_info.bmiHeader.biPlanes = 1;
289 bm_info.bmiHeader.biBitCount = 32;
290 bm_info.bmiHeader.biCompression = BI_RGB;
292 // ::CreateDIBSection allocates memory for us to copy our bitmap into.
293 // Unfortunately, we can't write the created bitmap to the clipboard,
294 // (see http://msdn2.microsoft.com/en-us/library/ms532292.aspx)
295 void *bits;
296 HBITMAP source_hbitmap =
297 ::CreateDIBSection(dc, &bm_info, DIB_RGB_COLORS, &bits, NULL, 0);
299 if (bits && source_hbitmap) {
301 SkAutoLockPixels bitmap_lock(bitmap);
302 // Copy the bitmap out of shared memory and into GDI
303 memcpy(bits, bitmap.getPixels(), bitmap.getSize());
306 // Now we have an HBITMAP, we can write it to the clipboard
307 WriteBitmapFromHandle(source_hbitmap,
308 gfx::Size(bitmap.width(), bitmap.height()));
311 ::DeleteObject(source_hbitmap);
312 ::ReleaseDC(NULL, dc);
315 void Clipboard::WriteBitmapFromHandle(HBITMAP source_hbitmap,
316 const gfx::Size& size) {
317 // We would like to just call ::SetClipboardData on the source_hbitmap,
318 // but that bitmap might not be of a sort we can write to the clipboard.
319 // For this reason, we create a new bitmap, copy the bits over, and then
320 // write that to the clipboard.
322 HDC dc = ::GetDC(NULL);
323 HDC compatible_dc = ::CreateCompatibleDC(NULL);
324 HDC source_dc = ::CreateCompatibleDC(NULL);
326 // This is the HBITMAP we will eventually write to the clipboard
327 HBITMAP hbitmap = ::CreateCompatibleBitmap(dc, size.width(), size.height());
328 if (!hbitmap) {
329 // Failed to create the bitmap
330 ::DeleteDC(compatible_dc);
331 ::DeleteDC(source_dc);
332 ::ReleaseDC(NULL, dc);
333 return;
336 HBITMAP old_hbitmap = (HBITMAP)SelectObject(compatible_dc, hbitmap);
337 HBITMAP old_source = (HBITMAP)SelectObject(source_dc, source_hbitmap);
339 // Now we need to blend it into an HBITMAP we can place on the clipboard
340 BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA};
341 ::GdiAlphaBlend(compatible_dc, 0, 0, size.width(), size.height(),
342 source_dc, 0, 0, size.width(), size.height(), bf);
344 // Clean up all the handles we just opened
345 ::SelectObject(compatible_dc, old_hbitmap);
346 ::SelectObject(source_dc, old_source);
347 ::DeleteObject(old_hbitmap);
348 ::DeleteObject(old_source);
349 ::DeleteDC(compatible_dc);
350 ::DeleteDC(source_dc);
351 ::ReleaseDC(NULL, dc);
353 WriteToClipboard(CF_BITMAP, hbitmap);
356 void Clipboard::WriteData(const FormatType& format,
357 const char* data_data,
358 size_t data_len) {
359 HGLOBAL hdata = ::GlobalAlloc(GMEM_MOVEABLE, data_len);
360 if (!hdata)
361 return;
363 char* data = static_cast<char*>(::GlobalLock(hdata));
364 memcpy(data, data_data, data_len);
365 ::GlobalUnlock(data);
366 WriteToClipboard(format.ToUINT(), hdata);
369 void Clipboard::WriteToClipboard(unsigned int format, HANDLE handle) {
370 DCHECK(clipboard_owner_->hwnd() != NULL);
371 if (handle && !::SetClipboardData(format, handle)) {
372 DCHECK(ERROR_CLIPBOARD_NOT_OPEN != GetLastError());
373 FreeData(format, handle);
377 uint64 Clipboard::GetSequenceNumber(ClipboardType type) {
378 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
379 return ::GetClipboardSequenceNumber();
382 bool Clipboard::IsFormatAvailable(const Clipboard::FormatType& format,
383 ClipboardType type) const {
384 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
385 return ::IsClipboardFormatAvailable(format.ToUINT()) != FALSE;
388 void Clipboard::Clear(ClipboardType type) {
389 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
390 ScopedClipboard clipboard;
391 if (!clipboard.Acquire(GetClipboardWindow()))
392 return;
394 ::EmptyClipboard();
397 void Clipboard::ReadAvailableTypes(ClipboardType type,
398 std::vector<base::string16>* types,
399 bool* contains_filenames) const {
400 if (!types || !contains_filenames) {
401 NOTREACHED();
402 return;
405 types->clear();
406 if (::IsClipboardFormatAvailable(GetPlainTextFormatType().ToUINT()))
407 types->push_back(base::UTF8ToUTF16(kMimeTypeText));
408 if (::IsClipboardFormatAvailable(GetHtmlFormatType().ToUINT()))
409 types->push_back(base::UTF8ToUTF16(kMimeTypeHTML));
410 if (::IsClipboardFormatAvailable(GetRtfFormatType().ToUINT()))
411 types->push_back(base::UTF8ToUTF16(kMimeTypeRTF));
412 if (::IsClipboardFormatAvailable(CF_DIB))
413 types->push_back(base::UTF8ToUTF16(kMimeTypePNG));
414 *contains_filenames = false;
416 // Acquire the clipboard.
417 ScopedClipboard clipboard;
418 if (!clipboard.Acquire(GetClipboardWindow()))
419 return;
421 HANDLE hdata = ::GetClipboardData(GetWebCustomDataFormatType().ToUINT());
422 if (!hdata)
423 return;
425 ReadCustomDataTypes(::GlobalLock(hdata), ::GlobalSize(hdata), types);
426 ::GlobalUnlock(hdata);
429 void Clipboard::ReadText(ClipboardType type, base::string16* result) const {
430 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
431 if (!result) {
432 NOTREACHED();
433 return;
436 result->clear();
438 // Acquire the clipboard.
439 ScopedClipboard clipboard;
440 if (!clipboard.Acquire(GetClipboardWindow()))
441 return;
443 HANDLE data = ::GetClipboardData(CF_UNICODETEXT);
444 if (!data)
445 return;
447 result->assign(static_cast<const base::char16*>(::GlobalLock(data)));
448 ::GlobalUnlock(data);
451 void Clipboard::ReadAsciiText(ClipboardType type, std::string* result) const {
452 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
453 if (!result) {
454 NOTREACHED();
455 return;
458 result->clear();
460 // Acquire the clipboard.
461 ScopedClipboard clipboard;
462 if (!clipboard.Acquire(GetClipboardWindow()))
463 return;
465 HANDLE data = ::GetClipboardData(CF_TEXT);
466 if (!data)
467 return;
469 result->assign(static_cast<const char*>(::GlobalLock(data)));
470 ::GlobalUnlock(data);
473 void Clipboard::ReadHTML(ClipboardType type,
474 base::string16* markup,
475 std::string* src_url,
476 uint32* fragment_start,
477 uint32* fragment_end) const {
478 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
480 markup->clear();
481 // TODO(dcheng): Remove these checks, I don't think they should be optional.
482 DCHECK(src_url);
483 if (src_url)
484 src_url->clear();
485 *fragment_start = 0;
486 *fragment_end = 0;
488 // Acquire the clipboard.
489 ScopedClipboard clipboard;
490 if (!clipboard.Acquire(GetClipboardWindow()))
491 return;
493 HANDLE data = ::GetClipboardData(GetHtmlFormatType().ToUINT());
494 if (!data)
495 return;
497 std::string cf_html(static_cast<const char*>(::GlobalLock(data)));
498 ::GlobalUnlock(data);
500 size_t html_start = std::string::npos;
501 size_t start_index = std::string::npos;
502 size_t end_index = std::string::npos;
503 ClipboardUtil::CFHtmlExtractMetadata(cf_html, src_url, &html_start,
504 &start_index, &end_index);
506 // This might happen if the contents of the clipboard changed and CF_HTML is
507 // no longer available.
508 if (start_index == std::string::npos ||
509 end_index == std::string::npos ||
510 html_start == std::string::npos)
511 return;
513 if (start_index < html_start || end_index < start_index)
514 return;
516 std::vector<size_t> offsets;
517 offsets.push_back(start_index - html_start);
518 offsets.push_back(end_index - html_start);
519 markup->assign(base::UTF8ToUTF16AndAdjustOffsets(cf_html.data() + html_start,
520 &offsets));
521 *fragment_start = base::checked_numeric_cast<uint32>(offsets[0]);
522 *fragment_end = base::checked_numeric_cast<uint32>(offsets[1]);
525 void Clipboard::ReadRTF(ClipboardType type, std::string* result) const {
526 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
528 ReadData(GetRtfFormatType(), result);
531 SkBitmap Clipboard::ReadImage(ClipboardType type) const {
532 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
534 // Acquire the clipboard.
535 ScopedClipboard clipboard;
536 if (!clipboard.Acquire(GetClipboardWindow()))
537 return SkBitmap();
539 // We use a DIB rather than a DDB here since ::GetObject() with the
540 // HBITMAP returned from ::GetClipboardData(CF_BITMAP) always reports a color
541 // depth of 32bpp.
542 BITMAPINFO* bitmap = static_cast<BITMAPINFO*>(::GetClipboardData(CF_DIB));
543 if (!bitmap)
544 return SkBitmap();
545 int color_table_length = 0;
546 switch (bitmap->bmiHeader.biBitCount) {
547 case 1:
548 case 4:
549 case 8:
550 color_table_length = bitmap->bmiHeader.biClrUsed
551 ? bitmap->bmiHeader.biClrUsed
552 : 1 << bitmap->bmiHeader.biBitCount;
553 break;
554 case 16:
555 case 32:
556 if (bitmap->bmiHeader.biCompression == BI_BITFIELDS)
557 color_table_length = 3;
558 break;
559 case 24:
560 break;
561 default:
562 NOTREACHED();
564 const void* bitmap_bits = reinterpret_cast<const char*>(bitmap)
565 + bitmap->bmiHeader.biSize + color_table_length * sizeof(RGBQUAD);
567 gfx::Canvas canvas(gfx::Size(bitmap->bmiHeader.biWidth,
568 bitmap->bmiHeader.biHeight),
569 1.0f,
570 false);
572 skia::ScopedPlatformPaint scoped_platform_paint(canvas.sk_canvas());
573 HDC dc = scoped_platform_paint.GetPlatformSurface();
574 ::SetDIBitsToDevice(dc, 0, 0, bitmap->bmiHeader.biWidth,
575 bitmap->bmiHeader.biHeight, 0, 0, 0,
576 bitmap->bmiHeader.biHeight, bitmap_bits, bitmap,
577 DIB_RGB_COLORS);
579 // Windows doesn't really handle alpha channels well in many situations. When
580 // the source image is < 32 bpp, we force the bitmap to be opaque. When the
581 // source image is 32 bpp, the alpha channel might still contain garbage data.
582 // Since Windows uses premultiplied alpha, we scan for instances where
583 // (R, G, B) > A. If there are any invalid premultiplied colors in the image,
584 // we assume the alpha channel contains garbage and force the bitmap to be
585 // opaque as well. Note that this heuristic will fail on a transparent bitmap
586 // containing only black pixels...
587 const SkBitmap& device_bitmap =
588 canvas.sk_canvas()->getDevice()->accessBitmap(true);
590 SkAutoLockPixels lock(device_bitmap);
591 bool has_invalid_alpha_channel = bitmap->bmiHeader.biBitCount < 32 ||
592 BitmapHasInvalidPremultipliedColors(device_bitmap);
593 if (has_invalid_alpha_channel) {
594 MakeBitmapOpaque(device_bitmap);
598 return canvas.ExtractImageRep().sk_bitmap();
601 void Clipboard::ReadCustomData(ClipboardType clipboard_type,
602 const base::string16& type,
603 base::string16* result) const {
604 DCHECK_EQ(clipboard_type, CLIPBOARD_TYPE_COPY_PASTE);
606 // Acquire the clipboard.
607 ScopedClipboard clipboard;
608 if (!clipboard.Acquire(GetClipboardWindow()))
609 return;
611 HANDLE hdata = ::GetClipboardData(GetWebCustomDataFormatType().ToUINT());
612 if (!hdata)
613 return;
615 ReadCustomDataForType(::GlobalLock(hdata), ::GlobalSize(hdata), type, result);
616 ::GlobalUnlock(hdata);
619 void Clipboard::ReadBookmark(base::string16* title, std::string* url) const {
620 if (title)
621 title->clear();
623 if (url)
624 url->clear();
626 // Acquire the clipboard.
627 ScopedClipboard clipboard;
628 if (!clipboard.Acquire(GetClipboardWindow()))
629 return;
631 HANDLE data = ::GetClipboardData(GetUrlWFormatType().ToUINT());
632 if (!data)
633 return;
635 base::string16 bookmark(static_cast<const base::char16*>(::GlobalLock(data)));
636 ::GlobalUnlock(data);
638 ParseBookmarkClipboardFormat(bookmark, title, url);
641 void Clipboard::ReadData(const FormatType& format, std::string* result) const {
642 if (!result) {
643 NOTREACHED();
644 return;
647 ScopedClipboard clipboard;
648 if (!clipboard.Acquire(GetClipboardWindow()))
649 return;
651 HANDLE data = ::GetClipboardData(format.ToUINT());
652 if (!data)
653 return;
655 result->assign(static_cast<const char*>(::GlobalLock(data)),
656 ::GlobalSize(data));
657 ::GlobalUnlock(data);
660 // static
661 void Clipboard::ParseBookmarkClipboardFormat(const base::string16& bookmark,
662 base::string16* title,
663 std::string* url) {
664 const base::string16 kDelim = base::ASCIIToUTF16("\r\n");
666 const size_t title_end = bookmark.find_first_of(kDelim);
667 if (title)
668 title->assign(bookmark.substr(0, title_end));
670 if (url) {
671 const size_t url_start = bookmark.find_first_not_of(kDelim, title_end);
672 if (url_start != base::string16::npos) {
673 *url = base::UTF16ToUTF8(
674 bookmark.substr(url_start, base::string16::npos));
679 // static
680 Clipboard::FormatType Clipboard::GetFormatType(
681 const std::string& format_string) {
682 return FormatType(
683 ::RegisterClipboardFormat(base::ASCIIToWide(format_string).c_str()));
686 // static
687 const Clipboard::FormatType& Clipboard::GetUrlFormatType() {
688 CR_DEFINE_STATIC_LOCAL(
689 FormatType, type, (::RegisterClipboardFormat(CFSTR_INETURLA)));
690 return type;
693 // static
694 const Clipboard::FormatType& Clipboard::GetUrlWFormatType() {
695 CR_DEFINE_STATIC_LOCAL(
696 FormatType, type, (::RegisterClipboardFormat(CFSTR_INETURLW)));
697 return type;
700 // static
701 const Clipboard::FormatType& Clipboard::GetMozUrlFormatType() {
702 CR_DEFINE_STATIC_LOCAL(
703 FormatType, type, (::RegisterClipboardFormat(L"text/x-moz-url")));
704 return type;
707 // static
708 const Clipboard::FormatType& Clipboard::GetPlainTextFormatType() {
709 CR_DEFINE_STATIC_LOCAL(FormatType, type, (CF_TEXT));
710 return type;
713 // static
714 const Clipboard::FormatType& Clipboard::GetPlainTextWFormatType() {
715 CR_DEFINE_STATIC_LOCAL(FormatType, type, (CF_UNICODETEXT));
716 return type;
719 // static
720 const Clipboard::FormatType& Clipboard::GetFilenameFormatType() {
721 CR_DEFINE_STATIC_LOCAL(
722 FormatType, type, (::RegisterClipboardFormat(CFSTR_FILENAMEA)));
723 return type;
726 // static
727 const Clipboard::FormatType& Clipboard::GetFilenameWFormatType() {
728 CR_DEFINE_STATIC_LOCAL(
729 FormatType, type, (::RegisterClipboardFormat(CFSTR_FILENAMEW)));
730 return type;
733 // MS HTML Format
734 // static
735 const Clipboard::FormatType& Clipboard::GetHtmlFormatType() {
736 CR_DEFINE_STATIC_LOCAL(
737 FormatType, type, (::RegisterClipboardFormat(L"HTML Format")));
738 return type;
741 // MS RTF Format
742 // static
743 const Clipboard::FormatType& Clipboard::GetRtfFormatType() {
744 CR_DEFINE_STATIC_LOCAL(
745 FormatType, type, (::RegisterClipboardFormat(L"Rich Text Format")));
746 return type;
749 // static
750 const Clipboard::FormatType& Clipboard::GetBitmapFormatType() {
751 CR_DEFINE_STATIC_LOCAL(FormatType, type, (CF_BITMAP));
752 return type;
755 // Firefox text/html
756 // static
757 const Clipboard::FormatType& Clipboard::GetTextHtmlFormatType() {
758 CR_DEFINE_STATIC_LOCAL(
759 FormatType, type, (::RegisterClipboardFormat(L"text/html")));
760 return type;
763 // static
764 const Clipboard::FormatType& Clipboard::GetCFHDropFormatType() {
765 CR_DEFINE_STATIC_LOCAL(FormatType, type, (CF_HDROP));
766 return type;
769 // static
770 const Clipboard::FormatType& Clipboard::GetFileDescriptorFormatType() {
771 CR_DEFINE_STATIC_LOCAL(
772 FormatType, type, (::RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR)));
773 return type;
776 // static
777 const Clipboard::FormatType& Clipboard::GetFileContentZeroFormatType() {
778 CR_DEFINE_STATIC_LOCAL(
779 FormatType, type, (::RegisterClipboardFormat(CFSTR_FILECONTENTS), 0));
780 return type;
783 // static
784 const Clipboard::FormatType& Clipboard::GetIDListFormatType() {
785 CR_DEFINE_STATIC_LOCAL(
786 FormatType, type, (::RegisterClipboardFormat(CFSTR_SHELLIDLIST)));
787 return type;
790 // static
791 const Clipboard::FormatType& Clipboard::GetWebKitSmartPasteFormatType() {
792 CR_DEFINE_STATIC_LOCAL(
793 FormatType,
794 type,
795 (::RegisterClipboardFormat(L"WebKit Smart Paste Format")));
796 return type;
799 // static
800 const Clipboard::FormatType& Clipboard::GetWebCustomDataFormatType() {
801 // TODO(dcheng): This name is temporary. See http://crbug.com/106449.
802 CR_DEFINE_STATIC_LOCAL(
803 FormatType,
804 type,
805 (::RegisterClipboardFormat(L"Chromium Web Custom MIME Data Format")));
806 return type;
809 // static
810 const Clipboard::FormatType& Clipboard::GetPepperCustomDataFormatType() {
811 CR_DEFINE_STATIC_LOCAL(
812 FormatType,
813 type,
814 (::RegisterClipboardFormat(L"Chromium Pepper MIME Data Format")));
815 return type;
818 // static
819 void Clipboard::FreeData(unsigned int format, HANDLE data) {
820 if (format == CF_BITMAP)
821 ::DeleteObject(static_cast<HBITMAP>(data));
822 else
823 ::GlobalFree(data);
826 HWND Clipboard::GetClipboardWindow() const {
827 if (!clipboard_owner_)
828 return NULL;
830 if (clipboard_owner_->hwnd() == NULL)
831 clipboard_owner_->Create(base::Bind(&ClipboardOwnerWndProc));
833 return clipboard_owner_->hwnd();
836 } // namespace ui