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 |
| 198 std::string Clipboard::FormatType::Serialize() const { |
| 199 return GdkAtomToString(data_); |
| 200 } |
| 201 |
| 202 // static |
| 203 Clipboard::FormatType Clipboard::FormatType::Deserialize( |
| 204 const std::string& serialization) { |
| 205 return FormatType(serialization); |
| 206 } |
| 207 |
| 208 bool Clipboard::FormatType::Equals(const FormatType& other) const { |
| 209 return data_ == other.data_; |
| 210 } |
| 211 |
183 Clipboard::Clipboard() : clipboard_data_(NULL) { | 212 Clipboard::Clipboard() : clipboard_data_(NULL) { |
184 #if !defined(USE_AURA) | |
185 clipboard_ = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); | 213 clipboard_ = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); |
186 primary_selection_ = gtk_clipboard_get(GDK_SELECTION_PRIMARY); | 214 primary_selection_ = gtk_clipboard_get(GDK_SELECTION_PRIMARY); |
187 #endif | |
188 } | 215 } |
189 | 216 |
190 Clipboard::~Clipboard() { | 217 Clipboard::~Clipboard() { |
191 gtk_clipboard_store(clipboard_); | 218 gtk_clipboard_store(clipboard_); |
192 } | 219 } |
193 | 220 |
194 void Clipboard::WriteObjects(const ObjectMap& objects) { | 221 void Clipboard::WriteObjects(const ObjectMap& objects) { |
195 clipboard_data_ = new TargetMap(); | 222 clipboard_data_ = new TargetMap(); |
196 | 223 |
197 for (ObjectMap::const_iterator iter = objects.begin(); | 224 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"); | 322 string16 url = UTF8ToUTF16(std::string(url_data, url_len) + "\n"); |
296 string16 title = UTF8ToUTF16(std::string(title_data, title_len)); | 323 string16 title = UTF8ToUTF16(std::string(title_data, title_len)); |
297 int data_len = 2 * (title.length() + url.length()); | 324 int data_len = 2 * (title.length() + url.length()); |
298 | 325 |
299 char* data = new char[data_len]; | 326 char* data = new char[data_len]; |
300 memcpy(data, url.data(), 2 * url.length()); | 327 memcpy(data, url.data(), 2 * url.length()); |
301 memcpy(data + 2 * url.length(), title.data(), 2 * title.length()); | 328 memcpy(data + 2 * url.length(), title.data(), 2 * title.length()); |
302 InsertMapping(kMimeTypeMozillaURL, data, data_len); | 329 InsertMapping(kMimeTypeMozillaURL, data, data_len); |
303 } | 330 } |
304 | 331 |
305 void Clipboard::WriteData(const char* format_name, size_t format_len, | 332 void Clipboard::WriteData(const FormatType& format, |
306 const char* data_data, size_t data_len) { | 333 const char* data_data, |
307 std::string format(format_name, format_len); | 334 size_t data_len) { |
308 // We assume that certain mapping types are only written by trusted code. | 335 // We assume that certain mapping types are only written by trusted code. |
309 // Therefore we must upkeep their integrity. | 336 // Therefore we must upkeep their integrity. |
310 if (format == kMimeTypeBitmap) | 337 if (format.Equals(GetBitmapFormatType())) |
311 return; | 338 return; |
312 char* data = new char[data_len]; | 339 char* data = new char[data_len]; |
313 memcpy(data, data_data, data_len); | 340 memcpy(data, data_data, data_len); |
314 InsertMapping(format.c_str(), data, data_len); | 341 // TODO(dcheng): Maybe this map should use GdkAtoms... |
| 342 InsertMapping(GdkAtomToString(format.ToGdkAtom()).c_str(), data, data_len); |
315 } | 343 } |
316 | 344 |
317 // We do not use gtk_clipboard_wait_is_target_available because of | 345 // We do not use gtk_clipboard_wait_is_target_available because of |
318 // a bug with the gtk clipboard. It caches the available targets | 346 // a bug with the gtk clipboard. It caches the available targets |
319 // and does not always refresh the cache when it is appropriate. | 347 // and does not always refresh the cache when it is appropriate. |
320 bool Clipboard::IsFormatAvailable(const Clipboard::FormatType& format, | 348 bool Clipboard::IsFormatAvailable(const Clipboard::FormatType& format, |
321 Clipboard::Buffer buffer) const { | 349 Clipboard::Buffer buffer) const { |
322 GtkClipboard* clipboard = LookupBackingClipboard(buffer); | 350 GtkClipboard* clipboard = LookupBackingClipboard(buffer); |
323 if (clipboard == NULL) | 351 if (clipboard == NULL) |
324 return false; | 352 return false; |
325 | 353 |
326 bool format_is_plain_text = GetPlainTextFormatType() == format; | 354 bool format_is_plain_text = GetPlainTextFormatType().Equals(format); |
327 if (format_is_plain_text) { | 355 if (format_is_plain_text) { |
328 // This tries a number of common text targets. | 356 // This tries a number of common text targets. |
329 if (gtk_clipboard_wait_is_text_available(clipboard)) | 357 if (gtk_clipboard_wait_is_text_available(clipboard)) |
330 return true; | 358 return true; |
331 } | 359 } |
332 | 360 |
333 bool retval = false; | 361 bool retval = false; |
334 GdkAtom* targets = NULL; | 362 GdkAtom* targets = NULL; |
335 GtkSelectionData* data = | 363 GtkSelectionData* data = |
336 gtk_clipboard_wait_for_contents(clipboard, | 364 gtk_clipboard_wait_for_contents(clipboard, |
(...skipping 13 matching lines...) Expand all Loading... |
350 if (num <= 0) { | 378 if (num <= 0) { |
351 if (format_is_plain_text) { | 379 if (format_is_plain_text) { |
352 gchar* text = gtk_clipboard_wait_for_text(clipboard); | 380 gchar* text = gtk_clipboard_wait_for_text(clipboard); |
353 if (text) { | 381 if (text) { |
354 g_free(text); | 382 g_free(text); |
355 retval = true; | 383 retval = true; |
356 } | 384 } |
357 } | 385 } |
358 } | 386 } |
359 | 387 |
360 GdkAtom format_atom = StringToGdkAtom(format); | |
361 | |
362 for (int i = 0; i < num; i++) { | 388 for (int i = 0; i < num; i++) { |
363 if (targets[i] == format_atom) { | 389 if (targets[i] == format.ToGdkAtom()) { |
364 retval = true; | 390 retval = true; |
365 break; | 391 break; |
366 } | 392 } |
367 } | 393 } |
368 | 394 |
369 g_free(targets); | 395 g_free(targets); |
370 gtk_selection_data_free(data); | 396 gtk_selection_data_free(data); |
371 | 397 |
372 return retval; | 398 return retval; |
373 } | 399 } |
374 | 400 |
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, | 401 void Clipboard::ReadAvailableTypes(Clipboard::Buffer buffer, |
381 std::vector<string16>* types, | 402 std::vector<string16>* types, |
382 bool* contains_filenames) const { | 403 bool* contains_filenames) const { |
383 if (!types || !contains_filenames) { | 404 if (!types || !contains_filenames) { |
384 NOTREACHED(); | 405 NOTREACHED(); |
385 return; | 406 return; |
386 } | 407 } |
387 | 408 |
388 types->clear(); | 409 types->clear(); |
389 if (IsFormatAvailable(GetPlainTextFormatType(), buffer)) | 410 if (IsFormatAvailable(GetPlainTextFormatType(), buffer)) |
390 types->push_back(UTF8ToUTF16(kMimeTypeText)); | 411 types->push_back(UTF8ToUTF16(kMimeTypeText)); |
391 if (IsFormatAvailable(GetHtmlFormatType(), buffer)) | 412 if (IsFormatAvailable(GetHtmlFormatType(), buffer)) |
392 types->push_back(UTF8ToUTF16(kMimeTypeHTML)); | 413 types->push_back(UTF8ToUTF16(kMimeTypeHTML)); |
393 if (IsFormatAvailable(GetBitmapFormatType(), buffer)) | 414 if (IsFormatAvailable(GetBitmapFormatType(), buffer)) |
394 types->push_back(UTF8ToUTF16(kMimeTypePNG)); | 415 types->push_back(UTF8ToUTF16(kMimeTypePNG)); |
395 *contains_filenames = false; | 416 *contains_filenames = false; |
396 | 417 |
397 GtkClipboard* clipboard = LookupBackingClipboard(buffer); | 418 GtkClipboard* clipboard = LookupBackingClipboard(buffer); |
398 if (!clipboard) | 419 if (!clipboard) |
399 return; | 420 return; |
400 | 421 |
401 GtkSelectionData* data = gtk_clipboard_wait_for_contents( | 422 GtkSelectionData* data = gtk_clipboard_wait_for_contents( |
402 clipboard, StringToGdkAtom(GetWebCustomDataFormatType())); | 423 clipboard, GetWebCustomDataFormatType().ToGdkAtom()); |
403 if (!data) | 424 if (!data) |
404 return; | 425 return; |
405 ReadCustomDataTypes(data->data, data->length, types); | 426 ReadCustomDataTypes(data->data, data->length, types); |
406 gtk_selection_data_free(data); | 427 gtk_selection_data_free(data); |
407 } | 428 } |
408 | 429 |
409 | 430 |
410 void Clipboard::ReadText(Clipboard::Buffer buffer, string16* result) const { | 431 void Clipboard::ReadText(Clipboard::Buffer buffer, string16* result) const { |
411 GtkClipboard* clipboard = LookupBackingClipboard(buffer); | 432 GtkClipboard* clipboard = LookupBackingClipboard(buffer); |
412 if (clipboard == NULL) | 433 if (clipboard == NULL) |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
451 markup->clear(); | 472 markup->clear(); |
452 if (src_url) | 473 if (src_url) |
453 src_url->clear(); | 474 src_url->clear(); |
454 *fragment_start = 0; | 475 *fragment_start = 0; |
455 *fragment_end = 0; | 476 *fragment_end = 0; |
456 | 477 |
457 GtkClipboard* clipboard = LookupBackingClipboard(buffer); | 478 GtkClipboard* clipboard = LookupBackingClipboard(buffer); |
458 if (clipboard == NULL) | 479 if (clipboard == NULL) |
459 return; | 480 return; |
460 GtkSelectionData* data = gtk_clipboard_wait_for_contents(clipboard, | 481 GtkSelectionData* data = gtk_clipboard_wait_for_contents(clipboard, |
461 StringToGdkAtom(GetHtmlFormatType())); | 482 GetHtmlFormatType().ToGdkAtom()); |
462 | 483 |
463 if (!data) | 484 if (!data) |
464 return; | 485 return; |
465 | 486 |
466 // If the data starts with 0xFEFF, i.e., Byte Order Mark, assume it is | 487 // If the data starts with 0xFEFF, i.e., Byte Order Mark, assume it is |
467 // UTF-16, otherwise assume UTF-8. | 488 // UTF-16, otherwise assume UTF-8. |
468 if (data->length >= 2 && | 489 if (data->length >= 2 && |
469 reinterpret_cast<uint16_t*>(data->data)[0] == 0xFEFF) { | 490 reinterpret_cast<uint16_t*>(data->data)[0] == 0xFEFF) { |
470 markup->assign(reinterpret_cast<uint16_t*>(data->data) + 1, | 491 markup->assign(reinterpret_cast<uint16_t*>(data->data) + 1, |
471 (data->length / 2) - 1); | 492 (data->length / 2) - 1); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
503 } | 524 } |
504 | 525 |
505 void Clipboard::ReadCustomData(Buffer buffer, | 526 void Clipboard::ReadCustomData(Buffer buffer, |
506 const string16& type, | 527 const string16& type, |
507 string16* result) const { | 528 string16* result) const { |
508 GtkClipboard* clipboard = LookupBackingClipboard(buffer); | 529 GtkClipboard* clipboard = LookupBackingClipboard(buffer); |
509 if (!clipboard) | 530 if (!clipboard) |
510 return; | 531 return; |
511 | 532 |
512 GtkSelectionData* data = gtk_clipboard_wait_for_contents( | 533 GtkSelectionData* data = gtk_clipboard_wait_for_contents( |
513 clipboard, StringToGdkAtom(GetWebCustomDataFormatType())); | 534 clipboard, GetWebCustomDataFormatType().ToGdkAtom()); |
514 if (!data) | 535 if (!data) |
515 return; | 536 return; |
516 ReadCustomDataForType(data->data, data->length, type, result); | 537 ReadCustomDataForType(data->data, data->length, type, result); |
517 gtk_selection_data_free(data); | 538 gtk_selection_data_free(data); |
518 } | 539 } |
519 | 540 |
520 void Clipboard::ReadBookmark(string16* title, std::string* url) const { | 541 void Clipboard::ReadBookmark(string16* title, std::string* url) const { |
521 // TODO(estade): implement this. | 542 // TODO(estade): implement this. |
522 NOTIMPLEMENTED(); | 543 NOTIMPLEMENTED(); |
523 } | 544 } |
524 | 545 |
525 void Clipboard::ReadData(const std::string& format, std::string* result) const { | 546 void Clipboard::ReadData(const FormatType& format, std::string* result) const { |
526 GtkSelectionData* data = | 547 GtkSelectionData* data = |
527 gtk_clipboard_wait_for_contents(clipboard_, StringToGdkAtom(format)); | 548 gtk_clipboard_wait_for_contents(clipboard_, format.ToGdkAtom()); |
528 if (!data) | 549 if (!data) |
529 return; | 550 return; |
530 result->assign(reinterpret_cast<char*>(data->data), data->length); | 551 result->assign(reinterpret_cast<char*>(data->data), data->length); |
531 gtk_selection_data_free(data); | 552 gtk_selection_data_free(data); |
532 } | 553 } |
533 | 554 |
534 uint64 Clipboard::GetSequenceNumber(Buffer buffer) { | 555 uint64 Clipboard::GetSequenceNumber(Buffer buffer) { |
535 if (buffer == BUFFER_STANDARD) | 556 if (buffer == BUFFER_STANDARD) |
536 return SelectionChangeObserver::GetInstance()->clipboard_sequence_number(); | 557 return SelectionChangeObserver::GetInstance()->clipboard_sequence_number(); |
537 else | 558 else |
538 return SelectionChangeObserver::GetInstance()->primary_sequence_number(); | 559 return SelectionChangeObserver::GetInstance()->primary_sequence_number(); |
539 } | 560 } |
540 | 561 |
541 // static | 562 //static |
542 Clipboard::FormatType Clipboard::GetPlainTextFormatType() { | 563 Clipboard::FormatType Clipboard::GetFormatType( |
543 return GdkAtomToString(GDK_TARGET_STRING); | 564 const std::string& format_string) { |
| 565 return FormatType::Deserialize(format_string); |
544 } | 566 } |
545 | 567 |
546 // static | 568 // static |
547 Clipboard::FormatType Clipboard::GetPlainTextWFormatType() { | 569 const Clipboard::FormatType& Clipboard::GetPlainTextFormatType() { |
| 570 CR_DEFINE_STATIC_LOCAL( |
| 571 FormatType, type, (GDK_TARGET_STRING)); |
| 572 return type; |
| 573 } |
| 574 |
| 575 // static |
| 576 const Clipboard::FormatType& Clipboard::GetPlainTextWFormatType() { |
548 return GetPlainTextFormatType(); | 577 return GetPlainTextFormatType(); |
549 } | 578 } |
550 | 579 |
551 // static | 580 // static |
552 Clipboard::FormatType Clipboard::GetHtmlFormatType() { | 581 const Clipboard::FormatType& Clipboard::GetHtmlFormatType() { |
553 return std::string(kMimeTypeHTML); | 582 CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeHTML)); |
| 583 return type; |
554 } | 584 } |
555 | 585 |
556 // static | 586 // static |
557 Clipboard::FormatType Clipboard::GetBitmapFormatType() { | 587 const Clipboard::FormatType& Clipboard::GetBitmapFormatType() { |
558 return std::string(kMimeTypeBitmap); | 588 CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeBitmap)); |
| 589 return type; |
559 } | 590 } |
560 | 591 |
561 // static | 592 // static |
562 Clipboard::FormatType Clipboard::GetWebKitSmartPasteFormatType() { | 593 const Clipboard::FormatType& Clipboard::GetWebKitSmartPasteFormatType() { |
563 return std::string(kMimeTypeWebkitSmartPaste); | 594 CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeWebkitSmartPaste)); |
| 595 return type; |
564 } | 596 } |
565 | 597 |
566 // static | 598 // static |
567 Clipboard::FormatType Clipboard::GetWebCustomDataFormatType() { | 599 const Clipboard::FormatType& Clipboard::GetWebCustomDataFormatType() { |
568 return std::string(kMimeTypeWebCustomData); | 600 CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeWebCustomData)); |
| 601 return type; |
569 } | 602 } |
570 | 603 |
571 void Clipboard::InsertMapping(const char* key, | 604 void Clipboard::InsertMapping(const char* key, |
572 char* data, | 605 char* data, |
573 size_t data_len) { | 606 size_t data_len) { |
574 DCHECK(clipboard_data_->find(key) == clipboard_data_->end()); | 607 DCHECK(clipboard_data_->find(key) == clipboard_data_->end()); |
575 (*clipboard_data_)[key] = std::make_pair(data, data_len); | 608 (*clipboard_data_)[key] = std::make_pair(data, data_len); |
576 } | 609 } |
577 | 610 |
578 GtkClipboard* Clipboard::LookupBackingClipboard(Buffer clipboard) const { | 611 GtkClipboard* Clipboard::LookupBackingClipboard(Buffer clipboard) const { |
579 switch (clipboard) { | 612 switch (clipboard) { |
580 case BUFFER_STANDARD: | 613 case BUFFER_STANDARD: |
581 return clipboard_; | 614 return clipboard_; |
582 case BUFFER_SELECTION: | 615 case BUFFER_SELECTION: |
583 return primary_selection_; | 616 return primary_selection_; |
584 default: | 617 default: |
585 NOTREACHED(); | 618 NOTREACHED(); |
586 return NULL; | 619 return NULL; |
587 } | 620 } |
588 } | 621 } |
589 | 622 |
590 } // namespace ui | 623 } // namespace ui |
OLD | NEW |