Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(82)

Side by Side Diff: ui/base/clipboard/clipboard_win.cc

Issue 658963003: Change Clipboard to use virtual methods for testing purposes. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: One more typo... Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // Many of these functions are based on those found in 5 // Many of these functions are based on those found in
6 // webkit/port/platform/PasteboardWin.cpp 6 // webkit/port/platform/PasteboardWin.cpp
7 7
8 #include "ui/base/clipboard/clipboard.h" 8 #include "ui/base/clipboard/clipboard_win.h"
9 9
10 #include <shellapi.h> 10 #include <shellapi.h>
11 #include <shlobj.h> 11 #include <shlobj.h>
12 12
13 #include "base/basictypes.h" 13 #include "base/basictypes.h"
14 #include "base/bind.h" 14 #include "base/bind.h"
15 #include "base/files/file_path.h" 15 #include "base/files/file_path.h"
16 #include "base/logging.h" 16 #include "base/logging.h"
17 #include "base/memory/shared_memory.h" 17 #include "base/memory/shared_memory.h"
18 #include "base/message_loop/message_loop.h" 18 #include "base/message_loop/message_loop.h"
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
152 } 152 }
153 153
154 void MakeBitmapOpaque(const SkBitmap& bitmap) { 154 void MakeBitmapOpaque(const SkBitmap& bitmap) {
155 for (int x = 0; x < bitmap.width(); ++x) { 155 for (int x = 0; x < bitmap.width(); ++x) {
156 for (int y = 0; y < bitmap.height(); ++y) { 156 for (int y = 0; y < bitmap.height(); ++y) {
157 *bitmap.getAddr32(x, y) = SkColorSetA(*bitmap.getAddr32(x, y), 0xFF); 157 *bitmap.getAddr32(x, y) = SkColorSetA(*bitmap.getAddr32(x, y), 0xFF);
158 } 158 }
159 } 159 }
160 } 160 }
161 161
162 void ParseBookmarkClipboardFormat(const base::string16& bookmark,
163 base::string16* title,
164 std::string* url) {
165 const base::string16 kDelim = base::ASCIIToUTF16("\r\n");
166
167 const size_t title_end = bookmark.find_first_of(kDelim);
168 if (title)
169 title->assign(bookmark.substr(0, title_end));
170
171 if (url) {
172 const size_t url_start = bookmark.find_first_not_of(kDelim, title_end);
173 if (url_start != base::string16::npos) {
174 *url =
175 base::UTF16ToUTF8(bookmark.substr(url_start, base::string16::npos));
176 }
177 }
178 }
179
180 void FreeData(unsigned int format, HANDLE data) {
181 if (format == CF_BITMAP)
182 ::DeleteObject(static_cast<HBITMAP>(data));
183 else
184 ::GlobalFree(data);
185 }
186
162 } // namespace 187 } // namespace
163 188
189 // Clipboard::FormatType implementation.
164 Clipboard::FormatType::FormatType() : data_() {} 190 Clipboard::FormatType::FormatType() : data_() {}
165 191
166 Clipboard::FormatType::FormatType(UINT native_format) : data_() { 192 Clipboard::FormatType::FormatType(UINT native_format) : data_() {
167 // There's no good way to actually initialize this in the constructor in 193 // There's no good way to actually initialize this in the constructor in
168 // C++03. 194 // C++03.
169 data_.cfFormat = native_format; 195 data_.cfFormat = native_format;
170 data_.dwAspect = DVASPECT_CONTENT; 196 data_.dwAspect = DVASPECT_CONTENT;
171 data_.lindex = -1; 197 data_.lindex = -1;
172 data_.tymed = TYMED_HGLOBAL; 198 data_.tymed = TYMED_HGLOBAL;
173 } 199 }
(...skipping 19 matching lines...) Expand all
193 const std::string& serialization) { 219 const std::string& serialization) {
194 int clipboard_format = -1; 220 int clipboard_format = -1;
195 if (!base::StringToInt(serialization, &clipboard_format)) { 221 if (!base::StringToInt(serialization, &clipboard_format)) {
196 NOTREACHED(); 222 NOTREACHED();
197 return FormatType(); 223 return FormatType();
198 } 224 }
199 return FormatType(clipboard_format); 225 return FormatType(clipboard_format);
200 } 226 }
201 227
202 bool Clipboard::FormatType::operator<(const FormatType& other) const { 228 bool Clipboard::FormatType::operator<(const FormatType& other) const {
203 return ToUINT() < other.ToUINT(); 229 return data_.cfFormat < other.data_.cfFormat;
204 } 230 }
205 231
206 bool Clipboard::FormatType::Equals(const FormatType& other) const { 232 bool Clipboard::FormatType::Equals(const FormatType& other) const {
207 return ToUINT() == other.ToUINT(); 233 return data_.cfFormat == other.data_.cfFormat;
208 } 234 }
209 235
210 Clipboard::Clipboard() { 236 // Miscellaneous Clipboard definitions.
237 // static
238 Clipboard::FormatType Clipboard::GetFormatType(
239 const std::string& format_string) {
240 return FormatType(
241 ::RegisterClipboardFormat(base::ASCIIToWide(format_string).c_str()));
242 }
243
244 // static
245 const Clipboard::FormatType& Clipboard::GetUrlFormatType() {
246 CR_DEFINE_STATIC_LOCAL(
247 FormatType, type, (::RegisterClipboardFormat(CFSTR_INETURLA)));
248 return type;
249 }
250
251 // static
252 const Clipboard::FormatType& Clipboard::GetUrlWFormatType() {
253 CR_DEFINE_STATIC_LOCAL(
254 FormatType, type, (::RegisterClipboardFormat(CFSTR_INETURLW)));
255 return type;
256 }
257
258 // static
259 const Clipboard::FormatType& Clipboard::GetMozUrlFormatType() {
260 CR_DEFINE_STATIC_LOCAL(
261 FormatType, type, (::RegisterClipboardFormat(L"text/x-moz-url")));
262 return type;
263 }
264
265 // static
266 const Clipboard::FormatType& Clipboard::GetPlainTextFormatType() {
267 CR_DEFINE_STATIC_LOCAL(FormatType, type, (CF_TEXT));
268 return type;
269 }
270
271 // static
272 const Clipboard::FormatType& Clipboard::GetPlainTextWFormatType() {
273 CR_DEFINE_STATIC_LOCAL(FormatType, type, (CF_UNICODETEXT));
274 return type;
275 }
276
277 // static
278 const Clipboard::FormatType& Clipboard::GetFilenameFormatType() {
279 CR_DEFINE_STATIC_LOCAL(
280 FormatType, type, (::RegisterClipboardFormat(CFSTR_FILENAMEA)));
281 return type;
282 }
283
284 // static
285 const Clipboard::FormatType& Clipboard::GetFilenameWFormatType() {
286 CR_DEFINE_STATIC_LOCAL(
287 FormatType, type, (::RegisterClipboardFormat(CFSTR_FILENAMEW)));
288 return type;
289 }
290
291 // MS HTML Format
292 // static
293 const Clipboard::FormatType& Clipboard::GetHtmlFormatType() {
294 CR_DEFINE_STATIC_LOCAL(
295 FormatType, type, (::RegisterClipboardFormat(L"HTML Format")));
296 return type;
297 }
298
299 // MS RTF Format
300 // static
301 const Clipboard::FormatType& Clipboard::GetRtfFormatType() {
302 CR_DEFINE_STATIC_LOCAL(
303 FormatType, type, (::RegisterClipboardFormat(L"Rich Text Format")));
304 return type;
305 }
306
307 // static
308 const Clipboard::FormatType& Clipboard::GetBitmapFormatType() {
309 CR_DEFINE_STATIC_LOCAL(FormatType, type, (CF_BITMAP));
310 return type;
311 }
312
313 // Firefox text/html
314 // static
315 const Clipboard::FormatType& Clipboard::GetTextHtmlFormatType() {
316 CR_DEFINE_STATIC_LOCAL(
317 FormatType, type, (::RegisterClipboardFormat(L"text/html")));
318 return type;
319 }
320
321 // static
322 const Clipboard::FormatType& Clipboard::GetCFHDropFormatType() {
323 CR_DEFINE_STATIC_LOCAL(FormatType, type, (CF_HDROP));
324 return type;
325 }
326
327 // static
328 const Clipboard::FormatType& Clipboard::GetFileDescriptorFormatType() {
329 CR_DEFINE_STATIC_LOCAL(
330 FormatType, type, (::RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR)));
331 return type;
332 }
333
334 // static
335 const Clipboard::FormatType& Clipboard::GetFileContentZeroFormatType() {
336 CR_DEFINE_STATIC_LOCAL(
337 FormatType, type, (::RegisterClipboardFormat(CFSTR_FILECONTENTS), 0));
338 return type;
339 }
340
341 // static
342 const Clipboard::FormatType& Clipboard::GetIDListFormatType() {
343 CR_DEFINE_STATIC_LOCAL(
344 FormatType, type, (::RegisterClipboardFormat(CFSTR_SHELLIDLIST)));
345 return type;
346 }
347
348 // static
349 const Clipboard::FormatType& Clipboard::GetWebKitSmartPasteFormatType() {
350 CR_DEFINE_STATIC_LOCAL(
351 FormatType,
352 type,
353 (::RegisterClipboardFormat(L"WebKit Smart Paste Format")));
354 return type;
355 }
356
357 // static
358 const Clipboard::FormatType& Clipboard::GetWebCustomDataFormatType() {
359 // TODO(dcheng): This name is temporary. See http://crbug.com/106449.
360 CR_DEFINE_STATIC_LOCAL(
361 FormatType,
362 type,
363 (::RegisterClipboardFormat(L"Chromium Web Custom MIME Data Format")));
364 return type;
365 }
366
367 // static
368 const Clipboard::FormatType& Clipboard::GetPepperCustomDataFormatType() {
369 CR_DEFINE_STATIC_LOCAL(
370 FormatType,
371 type,
372 (::RegisterClipboardFormat(L"Chromium Pepper MIME Data Format")));
373 return type;
374 }
375
376 // static
377 Clipboard* Clipboard::Create() {
378 return new ClipboardWin;
379 }
380
381 // ClipboardWin implementation.
382 ClipboardWin::ClipboardWin() {
211 if (base::MessageLoopForUI::IsCurrent()) 383 if (base::MessageLoopForUI::IsCurrent())
212 clipboard_owner_.reset(new base::win::MessageWindow()); 384 clipboard_owner_.reset(new base::win::MessageWindow());
213 } 385 }
214 386
215 Clipboard::~Clipboard() { 387 ClipboardWin::~ClipboardWin() {
216 } 388 }
217 389
218 void Clipboard::WriteObjects(ClipboardType type, const ObjectMap& objects) { 390 uint64 ClipboardWin::GetSequenceNumber(ClipboardType type) {
219 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
220
221 ScopedClipboard clipboard;
222 if (!clipboard.Acquire(GetClipboardWindow()))
223 return;
224
225 ::EmptyClipboard();
226
227 for (ObjectMap::const_iterator iter = objects.begin();
228 iter != objects.end(); ++iter) {
229 DispatchObject(static_cast<ObjectType>(iter->first), iter->second);
230 }
231 }
232
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);
237
238 WriteToClipboard(CF_UNICODETEXT, glob);
239 }
240
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;
247
248 if (url_len > 0)
249 url.assign(url_data, url_len);
250
251 std::string html_fragment = ClipboardUtil::HtmlToCFHtml(markup, url);
252 HGLOBAL glob = CreateGlobalData(html_fragment);
253
254 WriteToClipboard(Clipboard::GetHtmlFormatType().ToUINT(), glob);
255 }
256
257 void Clipboard::WriteRTF(const char* rtf_data, size_t data_len) {
258 WriteData(GetRtfFormatType(), rtf_data, data_len);
259 }
260
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);
268
269 base::string16 wide_bookmark = base::UTF8ToWide(bookmark);
270 HGLOBAL glob = CreateGlobalData(wide_bookmark);
271
272 WriteToClipboard(GetUrlWFormatType().ToUINT(), glob);
273 }
274
275 void Clipboard::WriteWebSmartPaste() {
276 DCHECK(clipboard_owner_->hwnd() != NULL);
277 ::SetClipboardData(GetWebKitSmartPasteFormatType().ToUINT(), NULL);
278 }
279
280 void Clipboard::WriteBitmap(const SkBitmap& bitmap) {
281 HDC dc = ::GetDC(NULL);
282
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.
286
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;
295
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);
302
303 if (bits && source_hbitmap) {
304 {
305 SkAutoLockPixels bitmap_lock(bitmap);
306 // Copy the bitmap out of shared memory and into GDI
307 memcpy(bits, bitmap.getPixels(), bitmap.getSize());
308 }
309
310 // Now we have an HBITMAP, we can write it to the clipboard
311 WriteBitmapFromHandle(source_hbitmap,
312 gfx::Size(bitmap.width(), bitmap.height()));
313 }
314
315 ::DeleteObject(source_hbitmap);
316 ::ReleaseDC(NULL, dc);
317 }
318
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.
325
326 HDC dc = ::GetDC(NULL);
327 HDC compatible_dc = ::CreateCompatibleDC(NULL);
328 HDC source_dc = ::CreateCompatibleDC(NULL);
329
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;
338 }
339
340 HBITMAP old_hbitmap = (HBITMAP)SelectObject(compatible_dc, hbitmap);
341 HBITMAP old_source = (HBITMAP)SelectObject(source_dc, source_hbitmap);
342
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);
347
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);
356
357 WriteToClipboard(CF_BITMAP, hbitmap);
358 }
359
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;
366
367 char* data = static_cast<char*>(::GlobalLock(hdata));
368 memcpy(data, data_data, data_len);
369 ::GlobalUnlock(data);
370 WriteToClipboard(format.ToUINT(), hdata);
371 }
372
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);
378 }
379 }
380
381 uint64 Clipboard::GetSequenceNumber(ClipboardType type) {
382 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); 391 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
383 return ::GetClipboardSequenceNumber(); 392 return ::GetClipboardSequenceNumber();
384 } 393 }
385 394
386 bool Clipboard::IsFormatAvailable(const Clipboard::FormatType& format, 395 bool ClipboardWin::IsFormatAvailable(const Clipboard::FormatType& format,
387 ClipboardType type) const { 396 ClipboardType type) const {
388 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); 397 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
389 return ::IsClipboardFormatAvailable(format.ToUINT()) != FALSE; 398 return ::IsClipboardFormatAvailable(format.ToFormatEtc().cfFormat) != FALSE;
390 } 399 }
391 400
392 void Clipboard::Clear(ClipboardType type) { 401 void ClipboardWin::Clear(ClipboardType type) {
393 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); 402 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
394 ScopedClipboard clipboard; 403 ScopedClipboard clipboard;
395 if (!clipboard.Acquire(GetClipboardWindow())) 404 if (!clipboard.Acquire(GetClipboardWindow()))
396 return; 405 return;
397 406
398 ::EmptyClipboard(); 407 ::EmptyClipboard();
399 } 408 }
400 409
401 void Clipboard::ReadAvailableTypes(ClipboardType type, 410 void ClipboardWin::ReadAvailableTypes(ClipboardType type,
402 std::vector<base::string16>* types, 411 std::vector<base::string16>* types,
403 bool* contains_filenames) const { 412 bool* contains_filenames) const {
404 if (!types || !contains_filenames) { 413 if (!types || !contains_filenames) {
405 NOTREACHED(); 414 NOTREACHED();
406 return; 415 return;
407 } 416 }
408 417
409 types->clear(); 418 types->clear();
410 if (::IsClipboardFormatAvailable(GetPlainTextFormatType().ToUINT())) 419 if (::IsClipboardFormatAvailable(
420 GetPlainTextFormatType().ToFormatEtc().cfFormat))
411 types->push_back(base::UTF8ToUTF16(kMimeTypeText)); 421 types->push_back(base::UTF8ToUTF16(kMimeTypeText));
412 if (::IsClipboardFormatAvailable(GetHtmlFormatType().ToUINT())) 422 if (::IsClipboardFormatAvailable(GetHtmlFormatType().ToFormatEtc().cfFormat))
413 types->push_back(base::UTF8ToUTF16(kMimeTypeHTML)); 423 types->push_back(base::UTF8ToUTF16(kMimeTypeHTML));
414 if (::IsClipboardFormatAvailable(GetRtfFormatType().ToUINT())) 424 if (::IsClipboardFormatAvailable(GetRtfFormatType().ToFormatEtc().cfFormat))
415 types->push_back(base::UTF8ToUTF16(kMimeTypeRTF)); 425 types->push_back(base::UTF8ToUTF16(kMimeTypeRTF));
416 if (::IsClipboardFormatAvailable(CF_DIB)) 426 if (::IsClipboardFormatAvailable(CF_DIB))
417 types->push_back(base::UTF8ToUTF16(kMimeTypePNG)); 427 types->push_back(base::UTF8ToUTF16(kMimeTypePNG));
418 *contains_filenames = false; 428 *contains_filenames = false;
419 429
420 // Acquire the clipboard. 430 // Acquire the clipboard.
421 ScopedClipboard clipboard; 431 ScopedClipboard clipboard;
422 if (!clipboard.Acquire(GetClipboardWindow())) 432 if (!clipboard.Acquire(GetClipboardWindow()))
423 return; 433 return;
424 434
425 HANDLE hdata = ::GetClipboardData(GetWebCustomDataFormatType().ToUINT()); 435 HANDLE hdata =
436 ::GetClipboardData(GetWebCustomDataFormatType().ToFormatEtc().cfFormat);
426 if (!hdata) 437 if (!hdata)
427 return; 438 return;
428 439
429 ReadCustomDataTypes(::GlobalLock(hdata), ::GlobalSize(hdata), types); 440 ReadCustomDataTypes(::GlobalLock(hdata), ::GlobalSize(hdata), types);
430 ::GlobalUnlock(hdata); 441 ::GlobalUnlock(hdata);
431 } 442 }
432 443
433 void Clipboard::ReadText(ClipboardType type, base::string16* result) const { 444 void ClipboardWin::ReadText(ClipboardType type, base::string16* result) const {
434 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); 445 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
435 if (!result) { 446 if (!result) {
436 NOTREACHED(); 447 NOTREACHED();
437 return; 448 return;
438 } 449 }
439 450
440 result->clear(); 451 result->clear();
441 452
442 // Acquire the clipboard. 453 // Acquire the clipboard.
443 ScopedClipboard clipboard; 454 ScopedClipboard clipboard;
444 if (!clipboard.Acquire(GetClipboardWindow())) 455 if (!clipboard.Acquire(GetClipboardWindow()))
445 return; 456 return;
446 457
447 HANDLE data = ::GetClipboardData(CF_UNICODETEXT); 458 HANDLE data = ::GetClipboardData(CF_UNICODETEXT);
448 if (!data) 459 if (!data)
449 return; 460 return;
450 461
451 result->assign(static_cast<const base::char16*>(::GlobalLock(data))); 462 result->assign(static_cast<const base::char16*>(::GlobalLock(data)));
452 ::GlobalUnlock(data); 463 ::GlobalUnlock(data);
453 } 464 }
454 465
455 void Clipboard::ReadAsciiText(ClipboardType type, std::string* result) const { 466 void ClipboardWin::ReadAsciiText(ClipboardType type,
467 std::string* result) const {
456 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); 468 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
457 if (!result) { 469 if (!result) {
458 NOTREACHED(); 470 NOTREACHED();
459 return; 471 return;
460 } 472 }
461 473
462 result->clear(); 474 result->clear();
463 475
464 // Acquire the clipboard. 476 // Acquire the clipboard.
465 ScopedClipboard clipboard; 477 ScopedClipboard clipboard;
466 if (!clipboard.Acquire(GetClipboardWindow())) 478 if (!clipboard.Acquire(GetClipboardWindow()))
467 return; 479 return;
468 480
469 HANDLE data = ::GetClipboardData(CF_TEXT); 481 HANDLE data = ::GetClipboardData(CF_TEXT);
470 if (!data) 482 if (!data)
471 return; 483 return;
472 484
473 result->assign(static_cast<const char*>(::GlobalLock(data))); 485 result->assign(static_cast<const char*>(::GlobalLock(data)));
474 ::GlobalUnlock(data); 486 ::GlobalUnlock(data);
475 } 487 }
476 488
477 void Clipboard::ReadHTML(ClipboardType type, 489 void ClipboardWin::ReadHTML(ClipboardType type,
478 base::string16* markup, 490 base::string16* markup,
479 std::string* src_url, 491 std::string* src_url,
480 uint32* fragment_start, 492 uint32* fragment_start,
481 uint32* fragment_end) const { 493 uint32* fragment_end) const {
482 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); 494 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
483 495
484 markup->clear(); 496 markup->clear();
485 // TODO(dcheng): Remove these checks, I don't think they should be optional. 497 // TODO(dcheng): Remove these checks, I don't think they should be optional.
486 DCHECK(src_url); 498 DCHECK(src_url);
487 if (src_url) 499 if (src_url)
488 src_url->clear(); 500 src_url->clear();
489 *fragment_start = 0; 501 *fragment_start = 0;
490 *fragment_end = 0; 502 *fragment_end = 0;
491 503
492 // Acquire the clipboard. 504 // Acquire the clipboard.
493 ScopedClipboard clipboard; 505 ScopedClipboard clipboard;
494 if (!clipboard.Acquire(GetClipboardWindow())) 506 if (!clipboard.Acquire(GetClipboardWindow()))
495 return; 507 return;
496 508
497 HANDLE data = ::GetClipboardData(GetHtmlFormatType().ToUINT()); 509 HANDLE data = ::GetClipboardData(GetHtmlFormatType().ToFormatEtc().cfFormat);
498 if (!data) 510 if (!data)
499 return; 511 return;
500 512
501 std::string cf_html(static_cast<const char*>(::GlobalLock(data))); 513 std::string cf_html(static_cast<const char*>(::GlobalLock(data)));
502 ::GlobalUnlock(data); 514 ::GlobalUnlock(data);
503 515
504 size_t html_start = std::string::npos; 516 size_t html_start = std::string::npos;
505 size_t start_index = std::string::npos; 517 size_t start_index = std::string::npos;
506 size_t end_index = std::string::npos; 518 size_t end_index = std::string::npos;
507 ClipboardUtil::CFHtmlExtractMetadata(cf_html, src_url, &html_start, 519 ClipboardUtil::CFHtmlExtractMetadata(cf_html, src_url, &html_start,
(...skipping 11 matching lines...) Expand all
519 531
520 std::vector<size_t> offsets; 532 std::vector<size_t> offsets;
521 offsets.push_back(start_index - html_start); 533 offsets.push_back(start_index - html_start);
522 offsets.push_back(end_index - html_start); 534 offsets.push_back(end_index - html_start);
523 markup->assign(base::UTF8ToUTF16AndAdjustOffsets(cf_html.data() + html_start, 535 markup->assign(base::UTF8ToUTF16AndAdjustOffsets(cf_html.data() + html_start,
524 &offsets)); 536 &offsets));
525 *fragment_start = base::checked_cast<uint32>(offsets[0]); 537 *fragment_start = base::checked_cast<uint32>(offsets[0]);
526 *fragment_end = base::checked_cast<uint32>(offsets[1]); 538 *fragment_end = base::checked_cast<uint32>(offsets[1]);
527 } 539 }
528 540
529 void Clipboard::ReadRTF(ClipboardType type, std::string* result) const { 541 void ClipboardWin::ReadRTF(ClipboardType type, std::string* result) const {
530 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); 542 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
531 543
532 ReadData(GetRtfFormatType(), result); 544 ReadData(GetRtfFormatType(), result);
533 } 545 }
534 546
535 SkBitmap Clipboard::ReadImage(ClipboardType type) const { 547 SkBitmap ClipboardWin::ReadImage(ClipboardType type) const {
536 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); 548 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
537 549
538 // Acquire the clipboard. 550 // Acquire the clipboard.
539 ScopedClipboard clipboard; 551 ScopedClipboard clipboard;
540 if (!clipboard.Acquire(GetClipboardWindow())) 552 if (!clipboard.Acquire(GetClipboardWindow()))
541 return SkBitmap(); 553 return SkBitmap();
542 554
543 // We use a DIB rather than a DDB here since ::GetObject() with the 555 // We use a DIB rather than a DDB here since ::GetObject() with the
544 // HBITMAP returned from ::GetClipboardData(CF_BITMAP) always reports a color 556 // HBITMAP returned from ::GetClipboardData(CF_BITMAP) always reports a color
545 // depth of 32bpp. 557 // depth of 32bpp.
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
595 bool has_invalid_alpha_channel = bitmap->bmiHeader.biBitCount < 32 || 607 bool has_invalid_alpha_channel = bitmap->bmiHeader.biBitCount < 32 ||
596 BitmapHasInvalidPremultipliedColors(device_bitmap); 608 BitmapHasInvalidPremultipliedColors(device_bitmap);
597 if (has_invalid_alpha_channel) { 609 if (has_invalid_alpha_channel) {
598 MakeBitmapOpaque(device_bitmap); 610 MakeBitmapOpaque(device_bitmap);
599 } 611 }
600 } 612 }
601 613
602 return canvas.ExtractImageRep().sk_bitmap(); 614 return canvas.ExtractImageRep().sk_bitmap();
603 } 615 }
604 616
605 void Clipboard::ReadCustomData(ClipboardType clipboard_type, 617 void ClipboardWin::ReadCustomData(ClipboardType clipboard_type,
606 const base::string16& type, 618 const base::string16& type,
607 base::string16* result) const { 619 base::string16* result) const {
608 DCHECK_EQ(clipboard_type, CLIPBOARD_TYPE_COPY_PASTE); 620 DCHECK_EQ(clipboard_type, CLIPBOARD_TYPE_COPY_PASTE);
609 621
610 // Acquire the clipboard. 622 // Acquire the clipboard.
611 ScopedClipboard clipboard; 623 ScopedClipboard clipboard;
612 if (!clipboard.Acquire(GetClipboardWindow())) 624 if (!clipboard.Acquire(GetClipboardWindow()))
613 return; 625 return;
614 626
615 HANDLE hdata = ::GetClipboardData(GetWebCustomDataFormatType().ToUINT()); 627 HANDLE hdata =
628 ::GetClipboardData(GetWebCustomDataFormatType().ToFormatEtc().cfFormat);
616 if (!hdata) 629 if (!hdata)
617 return; 630 return;
618 631
619 ReadCustomDataForType(::GlobalLock(hdata), ::GlobalSize(hdata), type, result); 632 ReadCustomDataForType(::GlobalLock(hdata), ::GlobalSize(hdata), type, result);
620 ::GlobalUnlock(hdata); 633 ::GlobalUnlock(hdata);
621 } 634 }
622 635
623 void Clipboard::ReadBookmark(base::string16* title, std::string* url) const { 636 void ClipboardWin::ReadBookmark(base::string16* title, std::string* url) const {
624 if (title) 637 if (title)
625 title->clear(); 638 title->clear();
626 639
627 if (url) 640 if (url)
628 url->clear(); 641 url->clear();
629 642
630 // Acquire the clipboard. 643 // Acquire the clipboard.
631 ScopedClipboard clipboard; 644 ScopedClipboard clipboard;
632 if (!clipboard.Acquire(GetClipboardWindow())) 645 if (!clipboard.Acquire(GetClipboardWindow()))
633 return; 646 return;
634 647
635 HANDLE data = ::GetClipboardData(GetUrlWFormatType().ToUINT()); 648 HANDLE data = ::GetClipboardData(GetUrlWFormatType().ToFormatEtc().cfFormat);
636 if (!data) 649 if (!data)
637 return; 650 return;
638 651
639 base::string16 bookmark(static_cast<const base::char16*>(::GlobalLock(data))); 652 base::string16 bookmark(static_cast<const base::char16*>(::GlobalLock(data)));
640 ::GlobalUnlock(data); 653 ::GlobalUnlock(data);
641 654
642 ParseBookmarkClipboardFormat(bookmark, title, url); 655 ParseBookmarkClipboardFormat(bookmark, title, url);
643 } 656 }
644 657
645 void Clipboard::ReadData(const FormatType& format, std::string* result) const { 658 void ClipboardWin::ReadData(const FormatType& format,
659 std::string* result) const {
646 if (!result) { 660 if (!result) {
647 NOTREACHED(); 661 NOTREACHED();
648 return; 662 return;
649 } 663 }
650 664
651 ScopedClipboard clipboard; 665 ScopedClipboard clipboard;
652 if (!clipboard.Acquire(GetClipboardWindow())) 666 if (!clipboard.Acquire(GetClipboardWindow()))
653 return; 667 return;
654 668
655 HANDLE data = ::GetClipboardData(format.ToUINT()); 669 HANDLE data = ::GetClipboardData(format.ToFormatEtc().cfFormat);
656 if (!data) 670 if (!data)
657 return; 671 return;
658 672
659 result->assign(static_cast<const char*>(::GlobalLock(data)), 673 result->assign(static_cast<const char*>(::GlobalLock(data)),
660 ::GlobalSize(data)); 674 ::GlobalSize(data));
661 ::GlobalUnlock(data); 675 ::GlobalUnlock(data);
662 } 676 }
663 677
664 // static 678 void ClipboardWin::WriteObjects(ClipboardType type, const ObjectMap& objects) {
665 void Clipboard::ParseBookmarkClipboardFormat(const base::string16& bookmark, 679 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
666 base::string16* title,
667 std::string* url) {
668 const base::string16 kDelim = base::ASCIIToUTF16("\r\n");
669 680
670 const size_t title_end = bookmark.find_first_of(kDelim); 681 ScopedClipboard clipboard;
671 if (title) 682 if (!clipboard.Acquire(GetClipboardWindow()))
672 title->assign(bookmark.substr(0, title_end)); 683 return;
673 684
674 if (url) { 685 ::EmptyClipboard();
675 const size_t url_start = bookmark.find_first_not_of(kDelim, title_end); 686
676 if (url_start != base::string16::npos) { 687 for (ObjectMap::const_iterator iter = objects.begin(); iter != objects.end();
677 *url = base::UTF16ToUTF8( 688 ++iter) {
678 bookmark.substr(url_start, base::string16::npos)); 689 DispatchObject(static_cast<ObjectType>(iter->first), iter->second);
679 }
680 } 690 }
681 } 691 }
682 692
683 // static 693 void ClipboardWin::WriteText(const char* text_data, size_t text_len) {
684 Clipboard::FormatType Clipboard::GetFormatType( 694 base::string16 text;
685 const std::string& format_string) { 695 base::UTF8ToUTF16(text_data, text_len, &text);
686 return FormatType( 696 HGLOBAL glob = CreateGlobalData(text);
687 ::RegisterClipboardFormat(base::ASCIIToWide(format_string).c_str())); 697
698 WriteToClipboard(CF_UNICODETEXT, glob);
688 } 699 }
689 700
690 // static 701 void ClipboardWin::WriteHTML(const char* markup_data,
691 const Clipboard::FormatType& Clipboard::GetUrlFormatType() { 702 size_t markup_len,
692 CR_DEFINE_STATIC_LOCAL( 703 const char* url_data,
693 FormatType, type, (::RegisterClipboardFormat(CFSTR_INETURLA))); 704 size_t url_len) {
694 return type; 705 std::string markup(markup_data, markup_len);
706 std::string url;
707
708 if (url_len > 0)
709 url.assign(url_data, url_len);
710
711 std::string html_fragment = ClipboardUtil::HtmlToCFHtml(markup, url);
712 HGLOBAL glob = CreateGlobalData(html_fragment);
713
714 WriteToClipboard(Clipboard::GetHtmlFormatType().ToFormatEtc().cfFormat, glob);
695 } 715 }
696 716
697 // static 717 void ClipboardWin::WriteRTF(const char* rtf_data, size_t data_len) {
698 const Clipboard::FormatType& Clipboard::GetUrlWFormatType() { 718 WriteData(GetRtfFormatType(), rtf_data, data_len);
699 CR_DEFINE_STATIC_LOCAL(
700 FormatType, type, (::RegisterClipboardFormat(CFSTR_INETURLW)));
701 return type;
702 } 719 }
703 720
704 // static 721 void ClipboardWin::WriteBookmark(const char* title_data,
705 const Clipboard::FormatType& Clipboard::GetMozUrlFormatType() { 722 size_t title_len,
706 CR_DEFINE_STATIC_LOCAL( 723 const char* url_data,
707 FormatType, type, (::RegisterClipboardFormat(L"text/x-moz-url"))); 724 size_t url_len) {
708 return type; 725 std::string bookmark(title_data, title_len);
726 bookmark.append(1, L'\n');
727 bookmark.append(url_data, url_len);
728
729 base::string16 wide_bookmark = base::UTF8ToWide(bookmark);
730 HGLOBAL glob = CreateGlobalData(wide_bookmark);
731
732 WriteToClipboard(GetUrlWFormatType().ToFormatEtc().cfFormat, glob);
709 } 733 }
710 734
711 // static 735 void ClipboardWin::WriteWebSmartPaste() {
712 const Clipboard::FormatType& Clipboard::GetPlainTextFormatType() { 736 DCHECK(clipboard_owner_->hwnd() != NULL);
713 CR_DEFINE_STATIC_LOCAL(FormatType, type, (CF_TEXT)); 737 ::SetClipboardData(GetWebKitSmartPasteFormatType().ToFormatEtc().cfFormat,
714 return type; 738 NULL);
715 } 739 }
716 740
717 // static 741 void ClipboardWin::WriteBitmap(const SkBitmap& bitmap) {
718 const Clipboard::FormatType& Clipboard::GetPlainTextWFormatType() { 742 HDC dc = ::GetDC(NULL);
719 CR_DEFINE_STATIC_LOCAL(FormatType, type, (CF_UNICODETEXT)); 743
720 return type; 744 // This doesn't actually cost us a memcpy when the bitmap comes from the
745 // renderer as we load it into the bitmap using setPixels which just sets a
746 // pointer. Someone has to memcpy it into GDI, it might as well be us here.
747
748 // TODO(darin): share data in gfx/bitmap_header.cc somehow
749 BITMAPINFO bm_info = {0};
750 bm_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
751 bm_info.bmiHeader.biWidth = bitmap.width();
752 bm_info.bmiHeader.biHeight = -bitmap.height(); // sets vertical orientation
753 bm_info.bmiHeader.biPlanes = 1;
754 bm_info.bmiHeader.biBitCount = 32;
755 bm_info.bmiHeader.biCompression = BI_RGB;
756
757 // ::CreateDIBSection allocates memory for us to copy our bitmap into.
758 // Unfortunately, we can't write the created bitmap to the clipboard,
759 // (see http://msdn2.microsoft.com/en-us/library/ms532292.aspx)
760 void* bits;
761 HBITMAP source_hbitmap =
762 ::CreateDIBSection(dc, &bm_info, DIB_RGB_COLORS, &bits, NULL, 0);
763
764 if (bits && source_hbitmap) {
765 {
766 SkAutoLockPixels bitmap_lock(bitmap);
767 // Copy the bitmap out of shared memory and into GDI
768 memcpy(bits, bitmap.getPixels(), bitmap.getSize());
769 }
770
771 // Now we have an HBITMAP, we can write it to the clipboard
772 WriteBitmapFromHandle(source_hbitmap,
773 gfx::Size(bitmap.width(), bitmap.height()));
774 }
775
776 ::DeleteObject(source_hbitmap);
777 ::ReleaseDC(NULL, dc);
721 } 778 }
722 779
723 // static 780 void ClipboardWin::WriteData(const FormatType& format,
724 const Clipboard::FormatType& Clipboard::GetFilenameFormatType() { 781 const char* data_data,
725 CR_DEFINE_STATIC_LOCAL( 782 size_t data_len) {
726 FormatType, type, (::RegisterClipboardFormat(CFSTR_FILENAMEA))); 783 HGLOBAL hdata = ::GlobalAlloc(GMEM_MOVEABLE, data_len);
727 return type; 784 if (!hdata)
785 return;
786
787 char* data = static_cast<char*>(::GlobalLock(hdata));
788 memcpy(data, data_data, data_len);
789 ::GlobalUnlock(data);
790 WriteToClipboard(format.ToFormatEtc().cfFormat, hdata);
728 } 791 }
729 792
730 // static 793 void ClipboardWin::WriteBitmapFromHandle(HBITMAP source_hbitmap,
731 const Clipboard::FormatType& Clipboard::GetFilenameWFormatType() { 794 const gfx::Size& size) {
732 CR_DEFINE_STATIC_LOCAL( 795 // We would like to just call ::SetClipboardData on the source_hbitmap,
733 FormatType, type, (::RegisterClipboardFormat(CFSTR_FILENAMEW))); 796 // but that bitmap might not be of a sort we can write to the clipboard.
734 return type; 797 // For this reason, we create a new bitmap, copy the bits over, and then
798 // write that to the clipboard.
799
800 HDC dc = ::GetDC(NULL);
801 HDC compatible_dc = ::CreateCompatibleDC(NULL);
802 HDC source_dc = ::CreateCompatibleDC(NULL);
803
804 // This is the HBITMAP we will eventually write to the clipboard
805 HBITMAP hbitmap = ::CreateCompatibleBitmap(dc, size.width(), size.height());
806 if (!hbitmap) {
807 // Failed to create the bitmap
808 ::DeleteDC(compatible_dc);
809 ::DeleteDC(source_dc);
810 ::ReleaseDC(NULL, dc);
811 return;
812 }
813
814 HBITMAP old_hbitmap = (HBITMAP)SelectObject(compatible_dc, hbitmap);
815 HBITMAP old_source = (HBITMAP)SelectObject(source_dc, source_hbitmap);
816
817 // Now we need to blend it into an HBITMAP we can place on the clipboard
818 BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA};
819 ::GdiAlphaBlend(compatible_dc,
820 0,
821 0,
822 size.width(),
823 size.height(),
824 source_dc,
825 0,
826 0,
827 size.width(),
828 size.height(),
829 bf);
830
831 // Clean up all the handles we just opened
832 ::SelectObject(compatible_dc, old_hbitmap);
833 ::SelectObject(source_dc, old_source);
834 ::DeleteObject(old_hbitmap);
835 ::DeleteObject(old_source);
836 ::DeleteDC(compatible_dc);
837 ::DeleteDC(source_dc);
838 ::ReleaseDC(NULL, dc);
839
840 WriteToClipboard(CF_BITMAP, hbitmap);
735 } 841 }
736 842
737 // MS HTML Format 843 void ClipboardWin::WriteToClipboard(unsigned int format, HANDLE handle) {
738 // static 844 DCHECK(clipboard_owner_->hwnd() != NULL);
739 const Clipboard::FormatType& Clipboard::GetHtmlFormatType() { 845 if (handle && !::SetClipboardData(format, handle)) {
740 CR_DEFINE_STATIC_LOCAL( 846 DCHECK(ERROR_CLIPBOARD_NOT_OPEN != GetLastError());
741 FormatType, type, (::RegisterClipboardFormat(L"HTML Format"))); 847 FreeData(format, handle);
742 return type; 848 }
743 } 849 }
744 850
745 // MS RTF Format 851 HWND ClipboardWin::GetClipboardWindow() const {
746 // static
747 const Clipboard::FormatType& Clipboard::GetRtfFormatType() {
748 CR_DEFINE_STATIC_LOCAL(
749 FormatType, type, (::RegisterClipboardFormat(L"Rich Text Format")));
750 return type;
751 }
752
753 // static
754 const Clipboard::FormatType& Clipboard::GetBitmapFormatType() {
755 CR_DEFINE_STATIC_LOCAL(FormatType, type, (CF_BITMAP));
756 return type;
757 }
758
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;
765 }
766
767 // static
768 const Clipboard::FormatType& Clipboard::GetCFHDropFormatType() {
769 CR_DEFINE_STATIC_LOCAL(FormatType, type, (CF_HDROP));
770 return type;
771 }
772
773 // static
774 const Clipboard::FormatType& Clipboard::GetFileDescriptorFormatType() {
775 CR_DEFINE_STATIC_LOCAL(
776 FormatType, type, (::RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR)));
777 return type;
778 }
779
780 // static
781 const Clipboard::FormatType& Clipboard::GetFileContentZeroFormatType() {
782 CR_DEFINE_STATIC_LOCAL(
783 FormatType, type, (::RegisterClipboardFormat(CFSTR_FILECONTENTS), 0));
784 return type;
785 }
786
787 // static
788 const Clipboard::FormatType& Clipboard::GetIDListFormatType() {
789 CR_DEFINE_STATIC_LOCAL(
790 FormatType, type, (::RegisterClipboardFormat(CFSTR_SHELLIDLIST)));
791 return type;
792 }
793
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;
801 }
802
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;
811 }
812
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;
820 }
821
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);
828 }
829
830 HWND Clipboard::GetClipboardWindow() const {
831 if (!clipboard_owner_) 852 if (!clipboard_owner_)
832 return NULL; 853 return NULL;
833 854
834 if (clipboard_owner_->hwnd() == NULL) 855 if (clipboard_owner_->hwnd() == NULL)
835 clipboard_owner_->Create(base::Bind(&ClipboardOwnerWndProc)); 856 clipboard_owner_->Create(base::Bind(&ClipboardOwnerWndProc));
836 857
837 return clipboard_owner_->hwnd(); 858 return clipboard_owner_->hwnd();
838 } 859 }
839 860
840 } // namespace ui 861 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698