| 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_android.h" | 5 #include "ui/base/clipboard/clipboard_android.h" | 
| 6 | 6 | 
| 7 #include <algorithm> | 7 #include <algorithm> | 
|  | 8 #include <utility> | 
| 8 | 9 | 
| 9 #include "base/android/context_utils.h" | 10 #include "base/android/context_utils.h" | 
| 10 #include "base/android/jni_string.h" | 11 #include "base/android/jni_string.h" | 
| 11 #include "base/android/scoped_java_ref.h" | 12 #include "base/android/scoped_java_ref.h" | 
|  | 13 #include "base/callback.h" | 
| 12 #include "base/lazy_instance.h" | 14 #include "base/lazy_instance.h" | 
| 13 #include "base/stl_util.h" | 15 #include "base/stl_util.h" | 
| 14 #include "base/strings/utf_string_conversions.h" | 16 #include "base/strings/utf_string_conversions.h" | 
| 15 #include "base/synchronization/lock.h" | 17 #include "base/synchronization/lock.h" | 
| 16 #include "base/time/time.h" | 18 #include "base/time/time.h" | 
| 17 #include "jni/Clipboard_jni.h" | 19 #include "jni/Clipboard_jni.h" | 
| 18 #include "third_party/skia/include/core/SkBitmap.h" | 20 #include "third_party/skia/include/core/SkBitmap.h" | 
| 19 #include "ui/gfx/geometry/size.h" | 21 #include "ui/gfx/geometry/size.h" | 
| 20 | 22 | 
| 21 // TODO:(andrewhayden) Support additional formats in Android: Bitmap, URI, HTML, | 23 // TODO:(andrewhayden) Support additional formats in Android: Bitmap, URI, HTML, | 
| (...skipping 23 matching lines...) Expand all  Loading... | 
| 45 const char kPlainTextFormat[] = "text"; | 47 const char kPlainTextFormat[] = "text"; | 
| 46 const char kHTMLFormat[] = "html"; | 48 const char kHTMLFormat[] = "html"; | 
| 47 const char kRTFFormat[] = "rtf"; | 49 const char kRTFFormat[] = "rtf"; | 
| 48 const char kBitmapFormat[] = "bitmap"; | 50 const char kBitmapFormat[] = "bitmap"; | 
| 49 const char kWebKitSmartPasteFormat[] = "webkit_smart"; | 51 const char kWebKitSmartPasteFormat[] = "webkit_smart"; | 
| 50 const char kBookmarkFormat[] = "bookmark"; | 52 const char kBookmarkFormat[] = "bookmark"; | 
| 51 | 53 | 
| 52 class ClipboardMap { | 54 class ClipboardMap { | 
| 53  public: | 55  public: | 
| 54   ClipboardMap(); | 56   ClipboardMap(); | 
|  | 57   void SetModifiedCallback(ClipboardAndroid::ModifiedCallback cb); | 
| 55   std::string Get(const std::string& format); | 58   std::string Get(const std::string& format); | 
| 56   uint64_t GetSequenceNumber() const; | 59   uint64_t GetSequenceNumber() const; | 
| 57   base::Time GetLastModifiedTime() const; | 60   base::Time GetLastModifiedTime() const; | 
| 58   void ClearLastModifiedTime(); | 61   void ClearLastModifiedTime(); | 
| 59   bool HasFormat(const std::string& format); | 62   bool HasFormat(const std::string& format); | 
| 60   void OnPrimaryClipboardChanged(); | 63   void OnPrimaryClipboardChanged(); | 
| 61   void Set(const std::string& format, const std::string& data); | 64   void Set(const std::string& format, const std::string& data); | 
| 62   void CommitToAndroidClipboard(); | 65   void CommitToAndroidClipboard(); | 
| 63   void Clear(); | 66   void Clear(); | 
| 64 | 67 | 
|  | 68   // Unlike the functions above, does not call |modified_cb_|. | 
|  | 69   void SetLastModifiedTimeWithoutRunningCallback(base::Time time); | 
|  | 70 | 
| 65  private: | 71  private: | 
| 66   enum class MapState { | 72   enum class MapState { | 
| 67     kOutOfDate, | 73     kOutOfDate, | 
| 68     kUpToDate, | 74     kUpToDate, | 
| 69     kPreparingCommit, | 75     kPreparingCommit, | 
| 70   }; | 76   }; | 
| 71 | 77 | 
|  | 78   // Updates |last_modified_time_| to |time| and writes it to |local_state_|. | 
|  | 79   void UpdateLastModifiedTime(base::Time time); | 
|  | 80 | 
|  | 81   // Updates |map_| and |map_state_| if necessary by fetching data from Java. | 
| 72   void UpdateFromAndroidClipboard(); | 82   void UpdateFromAndroidClipboard(); | 
|  | 83 | 
| 73   std::map<std::string, std::string> map_; | 84   std::map<std::string, std::string> map_; | 
| 74   MapState map_state_; | 85   MapState map_state_; | 
| 75   base::Lock lock_; | 86   base::Lock lock_; | 
| 76 | 87 | 
| 77   uint64_t sequence_number_; | 88   uint64_t sequence_number_; | 
| 78   base::Time last_modified_time_; | 89   base::Time last_modified_time_; | 
| 79 | 90 | 
|  | 91   ClipboardAndroid::ModifiedCallback modified_cb_; | 
|  | 92 | 
| 80   // Java class and methods for the Android ClipboardManager. | 93   // Java class and methods for the Android ClipboardManager. | 
| 81   ScopedJavaGlobalRef<jobject> clipboard_manager_; | 94   ScopedJavaGlobalRef<jobject> clipboard_manager_; | 
| 82 }; | 95 }; | 
| 83 base::LazyInstance<ClipboardMap>::Leaky g_map = LAZY_INSTANCE_INITIALIZER; | 96 base::LazyInstance<ClipboardMap>::Leaky g_map = LAZY_INSTANCE_INITIALIZER; | 
| 84 | 97 | 
| 85 ClipboardMap::ClipboardMap() : map_state_(MapState::kOutOfDate) { | 98 ClipboardMap::ClipboardMap() : map_state_(MapState::kOutOfDate) { | 
| 86   clipboard_manager_.Reset(Java_Clipboard_getInstance(AttachCurrentThread())); | 99   clipboard_manager_.Reset(Java_Clipboard_getInstance(AttachCurrentThread())); | 
| 87   DCHECK(clipboard_manager_.obj()); | 100   DCHECK(clipboard_manager_.obj()); | 
| 88 } | 101 } | 
| 89 | 102 | 
|  | 103 void ClipboardMap::SetModifiedCallback(ClipboardAndroid::ModifiedCallback cb) { | 
|  | 104   modified_cb_ = std::move(cb); | 
|  | 105 } | 
|  | 106 | 
| 90 std::string ClipboardMap::Get(const std::string& format) { | 107 std::string ClipboardMap::Get(const std::string& format) { | 
| 91   base::AutoLock lock(lock_); | 108   base::AutoLock lock(lock_); | 
| 92   UpdateFromAndroidClipboard(); | 109   UpdateFromAndroidClipboard(); | 
| 93   std::map<std::string, std::string>::const_iterator it = map_.find(format); | 110   std::map<std::string, std::string>::const_iterator it = map_.find(format); | 
| 94   return it == map_.end() ? std::string() : it->second; | 111   return it == map_.end() ? std::string() : it->second; | 
| 95 } | 112 } | 
| 96 | 113 | 
| 97 uint64_t ClipboardMap::GetSequenceNumber() const { | 114 uint64_t ClipboardMap::GetSequenceNumber() const { | 
| 98   return sequence_number_; | 115   return sequence_number_; | 
| 99 } | 116 } | 
| 100 | 117 | 
| 101 base::Time ClipboardMap::GetLastModifiedTime() const { | 118 base::Time ClipboardMap::GetLastModifiedTime() const { | 
| 102   return last_modified_time_; | 119   return last_modified_time_; | 
| 103 } | 120 } | 
| 104 | 121 | 
| 105 void ClipboardMap::ClearLastModifiedTime() { | 122 void ClipboardMap::ClearLastModifiedTime() { | 
| 106   last_modified_time_ = base::Time(); | 123   UpdateLastModifiedTime(base::Time()); | 
| 107 } | 124 } | 
| 108 | 125 | 
| 109 bool ClipboardMap::HasFormat(const std::string& format) { | 126 bool ClipboardMap::HasFormat(const std::string& format) { | 
| 110   base::AutoLock lock(lock_); | 127   base::AutoLock lock(lock_); | 
| 111   UpdateFromAndroidClipboard(); | 128   UpdateFromAndroidClipboard(); | 
| 112   return base::ContainsKey(map_, format); | 129   return base::ContainsKey(map_, format); | 
| 113 } | 130 } | 
| 114 | 131 | 
| 115 void ClipboardMap::OnPrimaryClipboardChanged() { | 132 void ClipboardMap::OnPrimaryClipboardChanged() { | 
| 116   sequence_number_++; | 133   sequence_number_++; | 
| 117   last_modified_time_ = base::Time::Now(); | 134   UpdateLastModifiedTime(base::Time::Now()); | 
| 118   map_state_ = MapState::kOutOfDate; | 135   map_state_ = MapState::kOutOfDate; | 
| 119 } | 136 } | 
| 120 | 137 | 
| 121 void ClipboardMap::Set(const std::string& format, const std::string& data) { | 138 void ClipboardMap::Set(const std::string& format, const std::string& data) { | 
| 122   base::AutoLock lock(lock_); | 139   base::AutoLock lock(lock_); | 
| 123   map_[format] = data; | 140   map_[format] = data; | 
| 124   map_state_ = MapState::kPreparingCommit; | 141   map_state_ = MapState::kPreparingCommit; | 
| 125 } | 142 } | 
| 126 | 143 | 
| 127 void ClipboardMap::CommitToAndroidClipboard() { | 144 void ClipboardMap::CommitToAndroidClipboard() { | 
| (...skipping 16 matching lines...) Expand all  Loading... | 
| 144     ScopedJavaLocalRef<jstring> str = | 161     ScopedJavaLocalRef<jstring> str = | 
| 145         ConvertUTF8ToJavaString(env, map_[kPlainTextFormat]); | 162         ConvertUTF8ToJavaString(env, map_[kPlainTextFormat]); | 
| 146     DCHECK(str.obj()); | 163     DCHECK(str.obj()); | 
| 147     Java_Clipboard_setText(env, clipboard_manager_, str); | 164     Java_Clipboard_setText(env, clipboard_manager_, str); | 
| 148   } else { | 165   } else { | 
| 149     Java_Clipboard_clear(env, clipboard_manager_); | 166     Java_Clipboard_clear(env, clipboard_manager_); | 
| 150     NOTIMPLEMENTED(); | 167     NOTIMPLEMENTED(); | 
| 151   } | 168   } | 
| 152   map_state_ = MapState::kUpToDate; | 169   map_state_ = MapState::kUpToDate; | 
| 153   sequence_number_++; | 170   sequence_number_++; | 
| 154   last_modified_time_ = base::Time::Now(); | 171   UpdateLastModifiedTime(base::Time::Now()); | 
| 155 } | 172 } | 
| 156 | 173 | 
| 157 void ClipboardMap::Clear() { | 174 void ClipboardMap::Clear() { | 
| 158   JNIEnv* env = AttachCurrentThread(); | 175   JNIEnv* env = AttachCurrentThread(); | 
| 159   base::AutoLock lock(lock_); | 176   base::AutoLock lock(lock_); | 
| 160   map_.clear(); | 177   map_.clear(); | 
| 161   Java_Clipboard_clear(env, clipboard_manager_); | 178   Java_Clipboard_clear(env, clipboard_manager_); | 
| 162   map_state_ = MapState::kUpToDate; | 179   map_state_ = MapState::kUpToDate; | 
| 163   sequence_number_++; | 180   sequence_number_++; | 
| 164   last_modified_time_ = base::Time::Now(); | 181   UpdateLastModifiedTime(base::Time::Now()); | 
|  | 182 } | 
|  | 183 | 
|  | 184 void ClipboardMap::SetLastModifiedTimeWithoutRunningCallback(base::Time time) { | 
|  | 185   last_modified_time_ = time; | 
| 165 } | 186 } | 
| 166 | 187 | 
| 167 // Add a key:jstr pair to map, but only if jstr is not null, and also | 188 // Add a key:jstr pair to map, but only if jstr is not null, and also | 
| 168 // not empty. | 189 // not empty. | 
| 169 void AddMapEntry(JNIEnv* env, | 190 void AddMapEntry(JNIEnv* env, | 
| 170                  std::map<std::string, std::string>* map, | 191                  std::map<std::string, std::string>* map, | 
| 171                  const char* key, | 192                  const char* key, | 
| 172                  const ScopedJavaLocalRef<jstring>& jstr) { | 193                  const ScopedJavaLocalRef<jstring>& jstr) { | 
| 173   if (!jstr.is_null()) { | 194   if (!jstr.is_null()) { | 
| 174     std::string str = ConvertJavaStringToUTF8(env, jstr.obj()); | 195     std::string str = ConvertJavaStringToUTF8(env, jstr.obj()); | 
| 175     if (!str.empty()) | 196     if (!str.empty()) | 
| 176       (*map)[key] = str; | 197       (*map)[key] = str; | 
| 177   } | 198   } | 
| 178 } | 199 } | 
| 179 | 200 | 
|  | 201 void ClipboardMap::UpdateLastModifiedTime(base::Time time) { | 
|  | 202   last_modified_time_ = time; | 
|  | 203   // |modified_callback_| may be null in tests. | 
|  | 204   if (modified_cb_) | 
|  | 205     modified_cb_.Run(time); | 
|  | 206 } | 
|  | 207 | 
| 180 void ClipboardMap::UpdateFromAndroidClipboard() { | 208 void ClipboardMap::UpdateFromAndroidClipboard() { | 
| 181   DCHECK_NE(MapState::kPreparingCommit, map_state_); | 209   DCHECK_NE(MapState::kPreparingCommit, map_state_); | 
| 182   if (map_state_ == MapState::kUpToDate) | 210   if (map_state_ == MapState::kUpToDate) | 
| 183     return; | 211     return; | 
| 184 | 212 | 
| 185   // Fetch the current Android clipboard state. | 213   // Fetch the current Android clipboard state. | 
| 186   lock_.AssertAcquired(); | 214   lock_.AssertAcquired(); | 
| 187   JNIEnv* env = AttachCurrentThread(); | 215   JNIEnv* env = AttachCurrentThread(); | 
| 188 | 216 | 
| 189   ScopedJavaLocalRef<jstring> jtext = | 217   ScopedJavaLocalRef<jstring> jtext = | 
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 296 } | 324 } | 
| 297 | 325 | 
| 298 // ClipboardAndroid implementation. | 326 // ClipboardAndroid implementation. | 
| 299 | 327 | 
| 300 void ClipboardAndroid::OnPrimaryClipChanged( | 328 void ClipboardAndroid::OnPrimaryClipChanged( | 
| 301     JNIEnv* env, | 329     JNIEnv* env, | 
| 302     const base::android::JavaParamRef<jobject>& obj) { | 330     const base::android::JavaParamRef<jobject>& obj) { | 
| 303   g_map.Get().OnPrimaryClipboardChanged(); | 331   g_map.Get().OnPrimaryClipboardChanged(); | 
| 304 } | 332 } | 
| 305 | 333 | 
|  | 334 void ClipboardAndroid::SetModifiedCallback(ModifiedCallback cb) { | 
|  | 335   g_map.Get().SetModifiedCallback(std::move(cb)); | 
|  | 336 } | 
|  | 337 | 
|  | 338 void ClipboardAndroid::SetLastModifiedTimeWithoutRunningCallback( | 
|  | 339     base::Time time) { | 
|  | 340   g_map.Get().SetLastModifiedTimeWithoutRunningCallback(time); | 
|  | 341 } | 
|  | 342 | 
| 306 ClipboardAndroid::ClipboardAndroid() { | 343 ClipboardAndroid::ClipboardAndroid() { | 
| 307   DCHECK(CalledOnValidThread()); | 344   DCHECK(CalledOnValidThread()); | 
| 308 } | 345 } | 
| 309 | 346 | 
| 310 ClipboardAndroid::~ClipboardAndroid() { | 347 ClipboardAndroid::~ClipboardAndroid() { | 
| 311   DCHECK(CalledOnValidThread()); | 348   DCHECK(CalledOnValidThread()); | 
| 312 } | 349 } | 
| 313 | 350 | 
| 314 void ClipboardAndroid::OnPreShutdown() {} | 351 void ClipboardAndroid::OnPreShutdown() {} | 
| 315 | 352 | 
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 513   return RegisterNativesImpl(env); | 550   return RegisterNativesImpl(env); | 
| 514 } | 551 } | 
| 515 | 552 | 
| 516 // Returns a pointer to the current ClipboardAndroid object. | 553 // Returns a pointer to the current ClipboardAndroid object. | 
| 517 static jlong Init(JNIEnv* env, | 554 static jlong Init(JNIEnv* env, | 
| 518                   const base::android::JavaParamRef<jobject>& obj) { | 555                   const base::android::JavaParamRef<jobject>& obj) { | 
| 519   return reinterpret_cast<intptr_t>(Clipboard::GetForCurrentThread()); | 556   return reinterpret_cast<intptr_t>(Clipboard::GetForCurrentThread()); | 
| 520 } | 557 } | 
| 521 | 558 | 
| 522 } // namespace ui | 559 } // namespace ui | 
| OLD | NEW | 
|---|