OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 #include "ui/base/clipboard/clipboard.h" | 5 #include "ui/base/clipboard/clipboard.h" |
6 | 6 |
7 #include <gtk/gtk.h> | 7 #include <gtk/gtk.h> |
8 #include <X11/extensions/Xfixes.h> | 8 #include <X11/extensions/Xfixes.h> |
9 #include <X11/Xatom.h> | 9 #include <X11/Xatom.h> |
10 #include <map> | 10 #include <map> |
11 #include <set> | 11 #include <set> |
12 #include <string> | 12 #include <string> |
13 #include <utility> | 13 #include <utility> |
14 | 14 |
| 15 #include "base/basictypes.h" |
15 #include "base/file_path.h" | 16 #include "base/file_path.h" |
16 #include "base/logging.h" | 17 #include "base/logging.h" |
17 #include "base/memory/singleton.h" | 18 #include "base/memory/singleton.h" |
18 #include "base/utf_string_conversions.h" | 19 #include "base/utf_string_conversions.h" |
19 #include "third_party/skia/include/core/SkBitmap.h" | 20 #include "third_party/skia/include/core/SkBitmap.h" |
20 #include "ui/base/clipboard/custom_data_helper.h" | 21 #include "ui/base/clipboard/custom_data_helper.h" |
21 #include "ui/base/gtk/gtk_signal.h" | 22 #include "ui/base/gtk/gtk_signal.h" |
22 #include "ui/base/x/x11_util.h" | 23 #include "ui/base/x/x11_util.h" |
23 #include "ui/gfx/canvas_skia.h" | 24 #include "ui/gfx/canvas_skia.h" |
24 #include "ui/gfx/gtk_util.h" | 25 #include "ui/gfx/gtk_util.h" |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
173 delete map; | 174 delete map; |
174 } | 175 } |
175 | 176 |
176 // Called on GdkPixbuf destruction; see WriteBitmap(). | 177 // Called on GdkPixbuf destruction; see WriteBitmap(). |
177 void GdkPixbufFree(guchar* pixels, gpointer data) { | 178 void GdkPixbufFree(guchar* pixels, gpointer data) { |
178 free(pixels); | 179 free(pixels); |
179 } | 180 } |
180 | 181 |
181 } // namespace | 182 } // namespace |
182 | 183 |
| 184 Clipboard::FormatType::FormatType() { |
| 185 } |
| 186 |
| 187 Clipboard::FormatType::FormatType(const std::string& format_string) |
| 188 : data_(StringToGdkAtom(format_string)) { |
| 189 } |
| 190 |
| 191 Clipboard::FormatType::FormatType(const GdkAtom& native_format) |
| 192 : data_(native_format) { |
| 193 } |
| 194 |
| 195 Clipboard::FormatType::~FormatType() { |
| 196 } |
| 197 |
183 Clipboard::Clipboard() : clipboard_data_(NULL) { | 198 Clipboard::Clipboard() : clipboard_data_(NULL) { |
184 #if !defined(USE_AURA) | |
185 clipboard_ = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); | 199 clipboard_ = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); |
186 primary_selection_ = gtk_clipboard_get(GDK_SELECTION_PRIMARY); | 200 primary_selection_ = gtk_clipboard_get(GDK_SELECTION_PRIMARY); |
187 #endif | |
188 } | 201 } |
189 | 202 |
190 Clipboard::~Clipboard() { | 203 Clipboard::~Clipboard() { |
191 gtk_clipboard_store(clipboard_); | 204 gtk_clipboard_store(clipboard_); |
192 } | 205 } |
193 | 206 |
194 void Clipboard::WriteObjects(const ObjectMap& objects) { | 207 void Clipboard::WriteObjects(const ObjectMap& objects) { |
195 clipboard_data_ = new TargetMap(); | 208 clipboard_data_ = new TargetMap(); |
196 | 209 |
197 for (ObjectMap::const_iterator iter = objects.begin(); | 210 for (ObjectMap::const_iterator iter = objects.begin(); |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 string16 url = UTF8ToUTF16(std::string(url_data, url_len) + "\n"); | 308 string16 url = UTF8ToUTF16(std::string(url_data, url_len) + "\n"); |
296 string16 title = UTF8ToUTF16(std::string(title_data, title_len)); | 309 string16 title = UTF8ToUTF16(std::string(title_data, title_len)); |
297 int data_len = 2 * (title.length() + url.length()); | 310 int data_len = 2 * (title.length() + url.length()); |
298 | 311 |
299 char* data = new char[data_len]; | 312 char* data = new char[data_len]; |
300 memcpy(data, url.data(), 2 * url.length()); | 313 memcpy(data, url.data(), 2 * url.length()); |
301 memcpy(data + 2 * url.length(), title.data(), 2 * title.length()); | 314 memcpy(data + 2 * url.length(), title.data(), 2 * title.length()); |
302 InsertMapping(kMimeTypeMozillaURL, data, data_len); | 315 InsertMapping(kMimeTypeMozillaURL, data, data_len); |
303 } | 316 } |
304 | 317 |
305 void Clipboard::WriteData(const char* format_name, size_t format_len, | 318 void Clipboard::WriteData(const FormatType& format, |
306 const char* data_data, size_t data_len) { | 319 const char* data_data, |
307 std::string format(format_name, format_len); | 320 size_t data_len) { |
308 // We assume that certain mapping types are only written by trusted code. | 321 // We assume that certain mapping types are only written by trusted code. |
309 // Therefore we must upkeep their integrity. | 322 // Therefore we must upkeep their integrity. |
310 if (format == kMimeTypeBitmap) | 323 if (format.data() == GetBitmapFormatType().data()) |
311 return; | 324 return; |
312 char* data = new char[data_len]; | 325 char* data = new char[data_len]; |
313 memcpy(data, data_data, data_len); | 326 memcpy(data, data_data, data_len); |
314 InsertMapping(format.c_str(), data, data_len); | 327 InsertMapping(GdkAtomToString(format.data()).c_str(), data, data_len); |
315 } | 328 } |
316 | 329 |
317 // We do not use gtk_clipboard_wait_is_target_available because of | 330 // We do not use gtk_clipboard_wait_is_target_available because of |
318 // a bug with the gtk clipboard. It caches the available targets | 331 // a bug with the gtk clipboard. It caches the available targets |
319 // and does not always refresh the cache when it is appropriate. | 332 // and does not always refresh the cache when it is appropriate. |
320 bool Clipboard::IsFormatAvailable(const Clipboard::FormatType& format, | 333 bool Clipboard::IsFormatAvailable(const Clipboard::FormatType& format, |
321 Clipboard::Buffer buffer) const { | 334 Clipboard::Buffer buffer) const { |
322 GtkClipboard* clipboard = LookupBackingClipboard(buffer); | 335 GtkClipboard* clipboard = LookupBackingClipboard(buffer); |
323 if (clipboard == NULL) | 336 if (clipboard == NULL) |
324 return false; | 337 return false; |
325 | 338 |
326 bool format_is_plain_text = GetPlainTextFormatType() == format; | 339 bool format_is_plain_text = |
| 340 GetPlainTextFormatType().data() == format.data(); |
327 if (format_is_plain_text) { | 341 if (format_is_plain_text) { |
328 // This tries a number of common text targets. | 342 // This tries a number of common text targets. |
329 if (gtk_clipboard_wait_is_text_available(clipboard)) | 343 if (gtk_clipboard_wait_is_text_available(clipboard)) |
330 return true; | 344 return true; |
331 } | 345 } |
332 | 346 |
333 bool retval = false; | 347 bool retval = false; |
334 GdkAtom* targets = NULL; | 348 GdkAtom* targets = NULL; |
335 GtkSelectionData* data = | 349 GtkSelectionData* data = |
336 gtk_clipboard_wait_for_contents(clipboard, | 350 gtk_clipboard_wait_for_contents(clipboard, |
(...skipping 13 matching lines...) Expand all Loading... |
350 if (num <= 0) { | 364 if (num <= 0) { |
351 if (format_is_plain_text) { | 365 if (format_is_plain_text) { |
352 gchar* text = gtk_clipboard_wait_for_text(clipboard); | 366 gchar* text = gtk_clipboard_wait_for_text(clipboard); |
353 if (text) { | 367 if (text) { |
354 g_free(text); | 368 g_free(text); |
355 retval = true; | 369 retval = true; |
356 } | 370 } |
357 } | 371 } |
358 } | 372 } |
359 | 373 |
360 GdkAtom format_atom = StringToGdkAtom(format); | |
361 | |
362 for (int i = 0; i < num; i++) { | 374 for (int i = 0; i < num; i++) { |
363 if (targets[i] == format_atom) { | 375 if (targets[i] == format.data()) { |
364 retval = true; | 376 retval = true; |
365 break; | 377 break; |
366 } | 378 } |
367 } | 379 } |
368 | 380 |
369 g_free(targets); | 381 g_free(targets); |
370 gtk_selection_data_free(data); | 382 gtk_selection_data_free(data); |
371 | 383 |
372 return retval; | 384 return retval; |
373 } | 385 } |
374 | 386 |
375 bool Clipboard::IsFormatAvailableByString(const std::string& format, | |
376 Clipboard::Buffer buffer) const { | |
377 return IsFormatAvailable(format, buffer); | |
378 } | |
379 | |
380 void Clipboard::ReadAvailableTypes(Clipboard::Buffer buffer, | 387 void Clipboard::ReadAvailableTypes(Clipboard::Buffer buffer, |
381 std::vector<string16>* types, | 388 std::vector<string16>* types, |
382 bool* contains_filenames) const { | 389 bool* contains_filenames) const { |
383 if (!types || !contains_filenames) { | 390 if (!types || !contains_filenames) { |
384 NOTREACHED(); | 391 NOTREACHED(); |
385 return; | 392 return; |
386 } | 393 } |
387 | 394 |
388 types->clear(); | 395 types->clear(); |
389 if (IsFormatAvailable(GetPlainTextFormatType(), buffer)) | 396 if (IsFormatAvailable(GetPlainTextFormatType(), buffer)) |
390 types->push_back(UTF8ToUTF16(kMimeTypeText)); | 397 types->push_back(UTF8ToUTF16(kMimeTypeText)); |
391 if (IsFormatAvailable(GetHtmlFormatType(), buffer)) | 398 if (IsFormatAvailable(GetHtmlFormatType(), buffer)) |
392 types->push_back(UTF8ToUTF16(kMimeTypeHTML)); | 399 types->push_back(UTF8ToUTF16(kMimeTypeHTML)); |
393 if (IsFormatAvailable(GetBitmapFormatType(), buffer)) | 400 if (IsFormatAvailable(GetBitmapFormatType(), buffer)) |
394 types->push_back(UTF8ToUTF16(kMimeTypePNG)); | 401 types->push_back(UTF8ToUTF16(kMimeTypePNG)); |
395 *contains_filenames = false; | 402 *contains_filenames = false; |
396 | 403 |
397 GtkClipboard* clipboard = LookupBackingClipboard(buffer); | 404 GtkClipboard* clipboard = LookupBackingClipboard(buffer); |
398 if (!clipboard) | 405 if (!clipboard) |
399 return; | 406 return; |
400 | 407 |
401 GtkSelectionData* data = gtk_clipboard_wait_for_contents( | 408 GtkSelectionData* data = gtk_clipboard_wait_for_contents( |
402 clipboard, StringToGdkAtom(GetWebCustomDataFormatType())); | 409 clipboard, GetWebCustomDataFormatType().data()); |
403 if (!data) | 410 if (!data) |
404 return; | 411 return; |
405 ReadCustomDataTypes(data->data, data->length, types); | 412 ReadCustomDataTypes(data->data, data->length, types); |
406 gtk_selection_data_free(data); | 413 gtk_selection_data_free(data); |
407 } | 414 } |
408 | 415 |
409 | 416 |
410 void Clipboard::ReadText(Clipboard::Buffer buffer, string16* result) const { | 417 void Clipboard::ReadText(Clipboard::Buffer buffer, string16* result) const { |
411 GtkClipboard* clipboard = LookupBackingClipboard(buffer); | 418 GtkClipboard* clipboard = LookupBackingClipboard(buffer); |
412 if (clipboard == NULL) | 419 if (clipboard == NULL) |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
451 markup->clear(); | 458 markup->clear(); |
452 if (src_url) | 459 if (src_url) |
453 src_url->clear(); | 460 src_url->clear(); |
454 *fragment_start = 0; | 461 *fragment_start = 0; |
455 *fragment_end = 0; | 462 *fragment_end = 0; |
456 | 463 |
457 GtkClipboard* clipboard = LookupBackingClipboard(buffer); | 464 GtkClipboard* clipboard = LookupBackingClipboard(buffer); |
458 if (clipboard == NULL) | 465 if (clipboard == NULL) |
459 return; | 466 return; |
460 GtkSelectionData* data = gtk_clipboard_wait_for_contents(clipboard, | 467 GtkSelectionData* data = gtk_clipboard_wait_for_contents(clipboard, |
461 StringToGdkAtom(GetHtmlFormatType())); | 468 GetHtmlFormatType().data()); |
462 | 469 |
463 if (!data) | 470 if (!data) |
464 return; | 471 return; |
465 | 472 |
466 // If the data starts with 0xFEFF, i.e., Byte Order Mark, assume it is | 473 // If the data starts with 0xFEFF, i.e., Byte Order Mark, assume it is |
467 // UTF-16, otherwise assume UTF-8. | 474 // UTF-16, otherwise assume UTF-8. |
468 if (data->length >= 2 && | 475 if (data->length >= 2 && |
469 reinterpret_cast<uint16_t*>(data->data)[0] == 0xFEFF) { | 476 reinterpret_cast<uint16_t*>(data->data)[0] == 0xFEFF) { |
470 markup->assign(reinterpret_cast<uint16_t*>(data->data) + 1, | 477 markup->assign(reinterpret_cast<uint16_t*>(data->data) + 1, |
471 (data->length / 2) - 1); | 478 (data->length / 2) - 1); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
503 } | 510 } |
504 | 511 |
505 void Clipboard::ReadCustomData(Buffer buffer, | 512 void Clipboard::ReadCustomData(Buffer buffer, |
506 const string16& type, | 513 const string16& type, |
507 string16* result) const { | 514 string16* result) const { |
508 GtkClipboard* clipboard = LookupBackingClipboard(buffer); | 515 GtkClipboard* clipboard = LookupBackingClipboard(buffer); |
509 if (!clipboard) | 516 if (!clipboard) |
510 return; | 517 return; |
511 | 518 |
512 GtkSelectionData* data = gtk_clipboard_wait_for_contents( | 519 GtkSelectionData* data = gtk_clipboard_wait_for_contents( |
513 clipboard, StringToGdkAtom(GetWebCustomDataFormatType())); | 520 clipboard, GetWebCustomDataFormatType().data()); |
514 if (!data) | 521 if (!data) |
515 return; | 522 return; |
516 ReadCustomDataForType(data->data, data->length, type, result); | 523 ReadCustomDataForType(data->data, data->length, type, result); |
517 gtk_selection_data_free(data); | 524 gtk_selection_data_free(data); |
518 } | 525 } |
519 | 526 |
520 void Clipboard::ReadBookmark(string16* title, std::string* url) const { | 527 void Clipboard::ReadBookmark(string16* title, std::string* url) const { |
521 // TODO(estade): implement this. | 528 // TODO(estade): implement this. |
522 NOTIMPLEMENTED(); | 529 NOTIMPLEMENTED(); |
523 } | 530 } |
524 | 531 |
525 void Clipboard::ReadData(const std::string& format, std::string* result) const { | 532 void Clipboard::ReadData(const FormatType& format, std::string* result) const { |
526 GtkSelectionData* data = | 533 GtkSelectionData* data = |
527 gtk_clipboard_wait_for_contents(clipboard_, StringToGdkAtom(format)); | 534 gtk_clipboard_wait_for_contents(clipboard_, format.data()); |
528 if (!data) | 535 if (!data) |
529 return; | 536 return; |
530 result->assign(reinterpret_cast<char*>(data->data), data->length); | 537 result->assign(reinterpret_cast<char*>(data->data), data->length); |
531 gtk_selection_data_free(data); | 538 gtk_selection_data_free(data); |
532 } | 539 } |
533 | 540 |
534 uint64 Clipboard::GetSequenceNumber(Buffer buffer) { | 541 uint64 Clipboard::GetSequenceNumber(Buffer buffer) { |
535 if (buffer == BUFFER_STANDARD) | 542 if (buffer == BUFFER_STANDARD) |
536 return SelectionChangeObserver::GetInstance()->clipboard_sequence_number(); | 543 return SelectionChangeObserver::GetInstance()->clipboard_sequence_number(); |
537 else | 544 else |
538 return SelectionChangeObserver::GetInstance()->primary_sequence_number(); | 545 return SelectionChangeObserver::GetInstance()->primary_sequence_number(); |
539 } | 546 } |
540 | 547 |
541 // static | 548 //static |
542 Clipboard::FormatType Clipboard::GetPlainTextFormatType() { | 549 Clipboard::FormatType Clipboard::RegisterFormatType( |
543 return GdkAtomToString(GDK_TARGET_STRING); | 550 const std::string& format_string) { |
| 551 return StringToFormatType(format_string); |
544 } | 552 } |
545 | 553 |
546 // static | 554 // static |
547 Clipboard::FormatType Clipboard::GetPlainTextWFormatType() { | 555 std::string Clipboard::FormatTypeToString(const FormatType& type) { |
| 556 return GdkAtomToString(type.data()); |
| 557 } |
| 558 |
| 559 // static |
| 560 Clipboard::FormatType Clipboard::StringToFormatType( |
| 561 const std::string& format_string) { |
| 562 return FormatType(StringToGdkAtom(format_string)); |
| 563 } |
| 564 |
| 565 // static |
| 566 const Clipboard::FormatType& Clipboard::GetPlainTextFormatType() { |
| 567 CR_DEFINE_STATIC_LOCAL( |
| 568 FormatType, type, (GDK_TARGET_STRING)); |
| 569 return type; |
| 570 } |
| 571 |
| 572 // static |
| 573 const Clipboard::FormatType& Clipboard::GetPlainTextWFormatType() { |
548 return GetPlainTextFormatType(); | 574 return GetPlainTextFormatType(); |
549 } | 575 } |
550 | 576 |
551 // static | 577 // static |
552 Clipboard::FormatType Clipboard::GetHtmlFormatType() { | 578 const Clipboard::FormatType& Clipboard::GetHtmlFormatType() { |
553 return std::string(kMimeTypeHTML); | 579 CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeHTML)); |
| 580 return type; |
554 } | 581 } |
555 | 582 |
556 // static | 583 // static |
557 Clipboard::FormatType Clipboard::GetBitmapFormatType() { | 584 const Clipboard::FormatType& Clipboard::GetBitmapFormatType() { |
558 return std::string(kMimeTypeBitmap); | 585 CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeBitmap)); |
| 586 return type; |
559 } | 587 } |
560 | 588 |
561 // static | 589 // static |
562 Clipboard::FormatType Clipboard::GetWebKitSmartPasteFormatType() { | 590 const Clipboard::FormatType& Clipboard::GetWebKitSmartPasteFormatType() { |
563 return std::string(kMimeTypeWebkitSmartPaste); | 591 CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeWebkitSmartPaste)); |
| 592 return type; |
564 } | 593 } |
565 | 594 |
566 // static | 595 // static |
567 Clipboard::FormatType Clipboard::GetWebCustomDataFormatType() { | 596 const Clipboard::FormatType& Clipboard::GetWebCustomDataFormatType() { |
568 return std::string(kMimeTypeWebCustomData); | 597 CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeWebCustomData)); |
| 598 return type; |
569 } | 599 } |
570 | 600 |
571 void Clipboard::InsertMapping(const char* key, | 601 void Clipboard::InsertMapping(const char* key, |
572 char* data, | 602 char* data, |
573 size_t data_len) { | 603 size_t data_len) { |
574 DCHECK(clipboard_data_->find(key) == clipboard_data_->end()); | 604 DCHECK(clipboard_data_->find(key) == clipboard_data_->end()); |
575 (*clipboard_data_)[key] = std::make_pair(data, data_len); | 605 (*clipboard_data_)[key] = std::make_pair(data, data_len); |
576 } | 606 } |
577 | 607 |
578 GtkClipboard* Clipboard::LookupBackingClipboard(Buffer clipboard) const { | 608 GtkClipboard* Clipboard::LookupBackingClipboard(Buffer clipboard) const { |
579 switch (clipboard) { | 609 switch (clipboard) { |
580 case BUFFER_STANDARD: | 610 case BUFFER_STANDARD: |
581 return clipboard_; | 611 return clipboard_; |
582 case BUFFER_SELECTION: | 612 case BUFFER_SELECTION: |
583 return primary_selection_; | 613 return primary_selection_; |
584 default: | 614 default: |
585 NOTREACHED(); | 615 NOTREACHED(); |
586 return NULL; | 616 return NULL; |
587 } | 617 } |
588 } | 618 } |
589 | 619 |
590 } // namespace ui | 620 } // namespace ui |
OLD | NEW |