OLD | NEW |
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 #include "ui/base/clipboard/clipboard.h" | 5 #include "ui/base/clipboard/clipboard.h" |
6 | 6 |
7 #include "base/android/jni_string.h" | 7 #include "base/android/jni_string.h" |
8 #include "base/lazy_instance.h" | 8 #include "base/lazy_instance.h" |
9 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
10 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
(...skipping 27 matching lines...) Expand all Loading... |
38 // Various formats we support. | 38 // Various formats we support. |
39 const char kPlainTextFormat[] = "text"; | 39 const char kPlainTextFormat[] = "text"; |
40 const char kHTMLFormat[] = "html"; | 40 const char kHTMLFormat[] = "html"; |
41 const char kRTFFormat[] = "rtf"; | 41 const char kRTFFormat[] = "rtf"; |
42 const char kBitmapFormat[] = "bitmap"; | 42 const char kBitmapFormat[] = "bitmap"; |
43 const char kWebKitSmartPasteFormat[] = "webkit_smart"; | 43 const char kWebKitSmartPasteFormat[] = "webkit_smart"; |
44 const char kBookmarkFormat[] = "bookmark"; | 44 const char kBookmarkFormat[] = "bookmark"; |
45 const char kMimeTypePepperCustomData[] = "chromium/x-pepper-custom-data"; | 45 const char kMimeTypePepperCustomData[] = "chromium/x-pepper-custom-data"; |
46 const char kMimeTypeWebCustomData[] = "chromium/x-web-custom-data"; | 46 const char kMimeTypeWebCustomData[] = "chromium/x-web-custom-data"; |
47 | 47 |
48 class ClipboardMap { | 48 class ClipboardMap : public ClipboardChangeListener { |
49 public: | 49 public: |
50 ClipboardMap(); | 50 ClipboardMap(); |
51 std::string Get(const std::string& format); | 51 std::string Get(const std::string& format); |
52 bool HasFormat(const std::string& format); | 52 bool HasFormat(const std::string& format); |
53 void Set(const std::string& format, const std::string& data); | 53 void Set(const std::string& format, const std::string& data); |
54 void Clear(); | 54 void Clear(); |
55 | 55 |
| 56 uint64 sequence_number() const { return sequence_number_; } |
| 57 |
56 private: | 58 private: |
| 59 // Called from Java when the clipboard changes. |
| 60 void OnChange(JNIEnv* env, jobject obj) OVERRIDE; |
| 61 |
57 void SyncWithAndroidClipboard(); | 62 void SyncWithAndroidClipboard(); |
58 std::map<std::string, std::string> map_; | 63 std::map<std::string, std::string> map_; |
59 base::Lock lock_; | 64 base::Lock lock_; |
60 | 65 |
61 // Java class and methods for the Android ClipboardManager. | 66 // Java class and methods for the Android ClipboardManager. |
62 ScopedJavaGlobalRef<jobject> clipboard_manager_; | 67 ScopedJavaGlobalRef<jobject> clipboard_manager_; |
| 68 uint64 sequence_number_; |
63 }; | 69 }; |
64 base::LazyInstance<ClipboardMap>::Leaky g_map = LAZY_INSTANCE_INITIALIZER; | 70 base::LazyInstance<ClipboardMap>::Leaky g_map = LAZY_INSTANCE_INITIALIZER; |
65 | 71 |
66 ClipboardMap::ClipboardMap() { | 72 ClipboardMap::ClipboardMap() : sequence_number_(0) { |
67 JNIEnv* env = AttachCurrentThread(); | 73 JNIEnv* env = AttachCurrentThread(); |
68 DCHECK(env); | 74 DCHECK(env); |
69 | 75 |
70 // Get the context. | 76 // Get the context. |
71 jobject context = base::android::GetApplicationContext(); | 77 jobject context = base::android::GetApplicationContext(); |
72 DCHECK(context); | 78 DCHECK(context); |
73 | 79 |
74 ScopedJavaLocalRef<jobject> local_ref = | 80 ScopedJavaLocalRef<jobject> local_ref = |
75 Java_Clipboard_create(env, context); | 81 Java_Clipboard_create(env, context); |
76 DCHECK(local_ref.obj()); | 82 DCHECK(local_ref.obj()); |
77 clipboard_manager_.Reset(env, local_ref.Release()); | 83 clipboard_manager_.Reset(env, local_ref.Release()); |
| 84 |
| 85 Java_Clipboard_addChangeListener( |
| 86 env, clipboard_manager_.obj(), reinterpret_cast<intptr_t>(this)); |
| 87 LOG(ERROR) << "Hello?"; |
78 } | 88 } |
79 | 89 |
80 std::string ClipboardMap::Get(const std::string& format) { | 90 std::string ClipboardMap::Get(const std::string& format) { |
81 base::AutoLock lock(lock_); | 91 base::AutoLock lock(lock_); |
82 SyncWithAndroidClipboard(); | 92 SyncWithAndroidClipboard(); |
83 std::map<std::string, std::string>::const_iterator it = map_.find(format); | 93 std::map<std::string, std::string>::const_iterator it = map_.find(format); |
84 return it == map_.end() ? std::string() : it->second; | 94 return it == map_.end() ? std::string() : it->second; |
85 } | 95 } |
86 | 96 |
87 bool ClipboardMap::HasFormat(const std::string& format) { | 97 bool ClipboardMap::HasFormat(const std::string& format) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
120 } | 130 } |
121 } | 131 } |
122 | 132 |
123 void ClipboardMap::Clear() { | 133 void ClipboardMap::Clear() { |
124 JNIEnv* env = AttachCurrentThread(); | 134 JNIEnv* env = AttachCurrentThread(); |
125 base::AutoLock lock(lock_); | 135 base::AutoLock lock(lock_); |
126 map_.clear(); | 136 map_.clear(); |
127 Java_Clipboard_setText(env, clipboard_manager_.obj(), NULL); | 137 Java_Clipboard_setText(env, clipboard_manager_.obj(), NULL); |
128 } | 138 } |
129 | 139 |
| 140 void ClipboardMap::OnChange(JNIEnv* env, jobject obj) { |
| 141 LOG(ERROR) << "Ping"; |
| 142 // TODO(dcheng): We may or may not need a lock here. |
| 143 ++sequence_number_; |
| 144 } |
| 145 |
130 // If the internal map contains a plain-text entry and it does not match that | 146 // If the internal map contains a plain-text entry and it does not match that |
131 // in the Android clipboard, clear the map and insert the Android text into it. | 147 // in the Android clipboard, clear the map and insert the Android text into it. |
132 // If there is an HTML entry in the Android clipboard it gets inserted in the | 148 // If there is an HTML entry in the Android clipboard it gets inserted in the |
133 // map. | 149 // map. |
134 void ClipboardMap::SyncWithAndroidClipboard() { | 150 void ClipboardMap::SyncWithAndroidClipboard() { |
135 lock_.AssertAcquired(); | 151 lock_.AssertAcquired(); |
136 JNIEnv* env = AttachCurrentThread(); | 152 JNIEnv* env = AttachCurrentThread(); |
137 | 153 |
138 // Update the plain text clipboard entry | 154 // Update the plain text clipboard entry |
139 std::map<std::string, std::string>::const_iterator it = | 155 std::map<std::string, std::string>::const_iterator it = |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); | 232 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); |
217 g_map.Get().Clear(); | 233 g_map.Get().Clear(); |
218 for (ObjectMap::const_iterator iter = objects.begin(); | 234 for (ObjectMap::const_iterator iter = objects.begin(); |
219 iter != objects.end(); ++iter) { | 235 iter != objects.end(); ++iter) { |
220 DispatchObject(static_cast<ObjectType>(iter->first), iter->second); | 236 DispatchObject(static_cast<ObjectType>(iter->first), iter->second); |
221 } | 237 } |
222 } | 238 } |
223 | 239 |
224 uint64 Clipboard::GetSequenceNumber(ClipboardType /* type */) { | 240 uint64 Clipboard::GetSequenceNumber(ClipboardType /* type */) { |
225 DCHECK(CalledOnValidThread()); | 241 DCHECK(CalledOnValidThread()); |
226 // TODO: implement this. For now this interface will advertise | 242 return g_map.Get().sequence_number(); |
227 // that the clipboard never changes. That's fine as long as we | |
228 // don't rely on this signal. | |
229 return 0; | |
230 } | 243 } |
231 | 244 |
232 bool Clipboard::IsFormatAvailable(const Clipboard::FormatType& format, | 245 bool Clipboard::IsFormatAvailable(const Clipboard::FormatType& format, |
233 ClipboardType type) const { | 246 ClipboardType type) const { |
234 DCHECK(CalledOnValidThread()); | 247 DCHECK(CalledOnValidThread()); |
235 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); | 248 DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); |
236 return g_map.Get().HasFormat(format.data()); | 249 return g_map.Get().HasFormat(format.data()); |
237 } | 250 } |
238 | 251 |
239 void Clipboard::Clear(ClipboardType type) { | 252 void Clipboard::Clear(ClipboardType type) { |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
382 return type; | 395 return type; |
383 } | 396 } |
384 | 397 |
385 // static | 398 // static |
386 const Clipboard::FormatType& Clipboard::GetPepperCustomDataFormatType() { | 399 const Clipboard::FormatType& Clipboard::GetPepperCustomDataFormatType() { |
387 CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypePepperCustomData)); | 400 CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypePepperCustomData)); |
388 return type; | 401 return type; |
389 } | 402 } |
390 | 403 |
391 void Clipboard::WriteText(const char* text_data, size_t text_len) { | 404 void Clipboard::WriteText(const char* text_data, size_t text_len) { |
| 405 DCHECK(CalledOnValidThread()); |
392 g_map.Get().Set(kPlainTextFormat, std::string(text_data, text_len)); | 406 g_map.Get().Set(kPlainTextFormat, std::string(text_data, text_len)); |
393 } | 407 } |
394 | 408 |
395 void Clipboard::WriteHTML(const char* markup_data, | 409 void Clipboard::WriteHTML(const char* markup_data, |
396 size_t markup_len, | 410 size_t markup_len, |
397 const char* url_data, | 411 const char* url_data, |
398 size_t url_len) { | 412 size_t url_len) { |
| 413 DCHECK(CalledOnValidThread()); |
399 g_map.Get().Set(kHTMLFormat, std::string(markup_data, markup_len)); | 414 g_map.Get().Set(kHTMLFormat, std::string(markup_data, markup_len)); |
400 } | 415 } |
401 | 416 |
402 void Clipboard::WriteRTF(const char* rtf_data, size_t data_len) { | 417 void Clipboard::WriteRTF(const char* rtf_data, size_t data_len) { |
| 418 DCHECK(CalledOnValidThread()); |
403 NOTIMPLEMENTED(); | 419 NOTIMPLEMENTED(); |
404 } | 420 } |
405 | 421 |
406 // Note: according to other platforms implementations, this really writes the | 422 // Note: according to other platforms implementations, this really writes the |
407 // URL spec. | 423 // URL spec. |
408 void Clipboard::WriteBookmark(const char* title_data, size_t title_len, | 424 void Clipboard::WriteBookmark(const char* title_data, size_t title_len, |
409 const char* url_data, size_t url_len) { | 425 const char* url_data, size_t url_len) { |
| 426 DCHECK(CalledOnValidThread()); |
410 g_map.Get().Set(kBookmarkFormat, std::string(url_data, url_len)); | 427 g_map.Get().Set(kBookmarkFormat, std::string(url_data, url_len)); |
411 } | 428 } |
412 | 429 |
413 // Write an extra flavor that signifies WebKit was the last to modify the | 430 // Write an extra flavor that signifies WebKit was the last to modify the |
414 // pasteboard. This flavor has no data. | 431 // pasteboard. This flavor has no data. |
415 void Clipboard::WriteWebSmartPaste() { | 432 void Clipboard::WriteWebSmartPaste() { |
| 433 DCHECK(CalledOnValidThread()); |
416 g_map.Get().Set(kWebKitSmartPasteFormat, std::string()); | 434 g_map.Get().Set(kWebKitSmartPasteFormat, std::string()); |
417 } | 435 } |
418 | 436 |
419 // Note: we implement this to pass all unit tests but it is currently unclear | 437 // Note: we implement this to pass all unit tests but it is currently unclear |
420 // how some code would consume this. | 438 // how some code would consume this. |
421 void Clipboard::WriteBitmap(const SkBitmap& bitmap) { | 439 void Clipboard::WriteBitmap(const SkBitmap& bitmap) { |
| 440 DCHECK(CalledOnValidThread()); |
422 gfx::Size size(bitmap.width(), bitmap.height()); | 441 gfx::Size size(bitmap.width(), bitmap.height()); |
423 | 442 |
424 std::string packed(reinterpret_cast<const char*>(&size), sizeof(size)); | 443 std::string packed(reinterpret_cast<const char*>(&size), sizeof(size)); |
425 { | 444 { |
426 SkAutoLockPixels bitmap_lock(bitmap); | 445 SkAutoLockPixels bitmap_lock(bitmap); |
427 packed += std::string(static_cast<const char*>(bitmap.getPixels()), | 446 packed += std::string(static_cast<const char*>(bitmap.getPixels()), |
428 bitmap.getSize()); | 447 bitmap.getSize()); |
429 } | 448 } |
430 g_map.Get().Set(kBitmapFormat, packed); | 449 g_map.Get().Set(kBitmapFormat, packed); |
431 } | 450 } |
432 | 451 |
433 void Clipboard::WriteData(const Clipboard::FormatType& format, | 452 void Clipboard::WriteData(const Clipboard::FormatType& format, |
434 const char* data_data, size_t data_len) { | 453 const char* data_data, size_t data_len) { |
| 454 DCHECK(CalledOnValidThread()); |
435 g_map.Get().Set(format.data(), std::string(data_data, data_len)); | 455 g_map.Get().Set(format.data(), std::string(data_data, data_len)); |
436 } | 456 } |
437 | 457 |
438 // See clipboard_android_initialization.h for more information. | 458 // See clipboard_android_initialization.h for more information. |
439 bool RegisterClipboardAndroid(JNIEnv* env) { | 459 bool RegisterClipboardAndroid(JNIEnv* env) { |
440 return RegisterNativesImpl(env); | 460 return RegisterNativesImpl(env); |
441 } | 461 } |
442 | 462 |
443 } // namespace ui | 463 } // namespace ui |
OLD | NEW |