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 |