| 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 |