Index: ui/base/clipboard/clipboard_android.cc |
diff --git a/ui/base/clipboard/clipboard_android.cc b/ui/base/clipboard/clipboard_android.cc |
index 8f35282acde0eb701fedebef5ec6aaaad0e84243..c2d57f6dd022aad5b1dcf3f563ab201b57018bb4 100644 |
--- a/ui/base/clipboard/clipboard_android.cc |
+++ b/ui/base/clipboard/clipboard_android.cc |
@@ -8,10 +8,12 @@ |
#include "base/android/context_utils.h" |
#include "base/android/jni_string.h" |
+#include "base/android/scoped_java_ref.h" |
#include "base/lazy_instance.h" |
#include "base/stl_util.h" |
#include "base/strings/utf_string_conversions.h" |
#include "base/synchronization/lock.h" |
+#include "base/time/time.h" |
#include "jni/Clipboard_jni.h" |
#include "third_party/skia/include/core/SkBitmap.h" |
#include "ui/gfx/geometry/size.h" |
@@ -37,6 +39,7 @@ using base::android::ScopedJavaLocalRef; |
namespace ui { |
namespace { |
+ |
// Various formats we support. |
const char kURLFormat[] = "url"; |
const char kPlainTextFormat[] = "text"; |
@@ -50,8 +53,11 @@ class ClipboardMap { |
public: |
ClipboardMap(); |
std::string Get(const std::string& format); |
- int64_t GetLastClipboardChangeTimeInMillis(); |
+ uint64_t GetSequenceNumber() const; |
+ base::Time GetLastModifiedTime() const; |
+ void ClearLastModifiedTime(); |
bool HasFormat(const std::string& format); |
+ void OnPrimaryClipboardChanged(); |
void Set(const std::string& format, const std::string& data); |
void CommitToAndroidClipboard(); |
void Clear(); |
@@ -59,9 +65,11 @@ class ClipboardMap { |
private: |
void UpdateFromAndroidClipboard(); |
std::map<std::string, std::string> map_; |
+ bool map_up_to_date_; |
base::Lock lock_; |
- int64_t last_clipboard_change_time_ms_; |
+ uint64_t sequence_number_; |
+ base::Time last_modified_time_; |
// Java class and methods for the Android ClipboardManager. |
ScopedJavaGlobalRef<jobject> clipboard_manager_; |
@@ -71,6 +79,7 @@ base::LazyInstance<ClipboardMap>::Leaky g_map = LAZY_INSTANCE_INITIALIZER; |
ClipboardMap::ClipboardMap() { |
clipboard_manager_.Reset(Java_Clipboard_getInstance(AttachCurrentThread())); |
DCHECK(clipboard_manager_.obj()); |
+ map_up_to_date_ = false; |
dcheng
2017/04/13 20:35:37
Nit: use the initializer list (or use in-class ini
Mark P
2017/04/13 20:54:05
Done.
|
} |
std::string ClipboardMap::Get(const std::string& format) { |
@@ -80,10 +89,16 @@ std::string ClipboardMap::Get(const std::string& format) { |
return it == map_.end() ? std::string() : it->second; |
} |
-int64_t ClipboardMap::GetLastClipboardChangeTimeInMillis() { |
- base::AutoLock lock(lock_); |
- UpdateFromAndroidClipboard(); |
- return last_clipboard_change_time_ms_; |
+uint64_t ClipboardMap::GetSequenceNumber() const { |
+ return sequence_number_; |
+} |
+ |
+base::Time ClipboardMap::GetLastModifiedTime() const { |
+ return last_modified_time_; |
+} |
+ |
+void ClipboardMap::ClearLastModifiedTime() { |
+ last_modified_time_ = base::Time(); |
} |
bool ClipboardMap::HasFormat(const std::string& format) { |
@@ -92,9 +107,16 @@ bool ClipboardMap::HasFormat(const std::string& format) { |
return base::ContainsKey(map_, format); |
} |
+void ClipboardMap::OnPrimaryClipboardChanged() { |
+ sequence_number_++; |
+ last_modified_time_ = base::Time::Now(); |
+ map_up_to_date_ = false; |
+} |
+ |
void ClipboardMap::Set(const std::string& format, const std::string& data) { |
base::AutoLock lock(lock_); |
map_[format] = data; |
+ map_up_to_date_ = false; |
dcheng
2017/04/13 20:35:37
Can we make this a tri-state enum? Calling UpdateF
Mark P
2017/04/13 20:54:05
Do you mean
MAP_OUT_OF_DATE
MAP_FRESHER_THAN_JAVA
dcheng
2017/04/13 20:59:18
MAP_OUT_OF_DATE
MAP_UP_TO_DATE
MAP_PREPARING_COMMI
Mark P
2017/04/13 21:21:46
Done with the scoped enum. Please take a look.
T
|
} |
void ClipboardMap::CommitToAndroidClipboard() { |
@@ -122,6 +144,9 @@ void ClipboardMap::CommitToAndroidClipboard() { |
Java_Clipboard_clear(env, clipboard_manager_); |
NOTIMPLEMENTED(); |
} |
+ map_up_to_date_ = true; |
+ sequence_number_++; |
+ last_modified_time_ = base::Time::Now(); |
} |
void ClipboardMap::Clear() { |
@@ -129,6 +154,9 @@ void ClipboardMap::Clear() { |
base::AutoLock lock(lock_); |
map_.clear(); |
Java_Clipboard_clear(env, clipboard_manager_); |
+ map_up_to_date_ = true; |
+ sequence_number_++; |
+ last_modified_time_ = base::Time::Now(); |
} |
// Add a key:jstr pair to map, but only if jstr is not null, and also |
@@ -144,38 +172,23 @@ void AddMapEntry(JNIEnv* env, |
} |
} |
-// Return true if all the key-value pairs in map1 are also in map2. |
-bool MapIsSubset(const std::map<std::string, std::string>& map1, |
- const std::map<std::string, std::string>& map2) { |
- for (const auto& val : map1) { |
- auto iter = map2.find(val.first); |
- if (iter == map2.end() || iter->second != val.second) |
- return false; |
- } |
- return true; |
-} |
- |
void ClipboardMap::UpdateFromAndroidClipboard() { |
- // Fetch the current Android clipboard state. Replace our state with |
- // the Android state if the Android state has been changed. |
+ if (map_up_to_date_) |
+ return; |
+ |
+ // Fetch the current Android clipboard state. |
lock_.AssertAcquired(); |
JNIEnv* env = AttachCurrentThread(); |
- std::map<std::string, std::string> android_clipboard_state; |
- |
ScopedJavaLocalRef<jstring> jtext = |
Java_Clipboard_getCoercedText(env, clipboard_manager_); |
ScopedJavaLocalRef<jstring> jhtml = |
Java_Clipboard_getHTMLText(env, clipboard_manager_); |
- AddMapEntry(env, &android_clipboard_state, kPlainTextFormat, jtext); |
- AddMapEntry(env, &android_clipboard_state, kHTMLFormat, jhtml); |
- last_clipboard_change_time_ms_ = |
- Java_Clipboard_getClipboardContentChangeTimeInMillis(env, |
- clipboard_manager_); |
+ AddMapEntry(env, &map_, kPlainTextFormat, jtext); |
+ AddMapEntry(env, &map_, kHTMLFormat, jhtml); |
- if (!MapIsSubset(android_clipboard_state, map_)) |
- android_clipboard_state.swap(map_); |
+ map_up_to_date_ = true; |
} |
} // namespace |
@@ -277,6 +290,13 @@ Clipboard* Clipboard::Create() { |
} |
// ClipboardAndroid implementation. |
+ |
+void ClipboardAndroid::OnPrimaryClipChanged( |
+ JNIEnv* env, |
+ const base::android::JavaParamRef<jobject>& obj) { |
+ g_map.Get().OnPrimaryClipboardChanged(); |
+} |
+ |
ClipboardAndroid::ClipboardAndroid() { |
DCHECK(CalledOnValidThread()); |
} |
@@ -289,10 +309,7 @@ void ClipboardAndroid::OnPreShutdown() {} |
uint64_t ClipboardAndroid::GetSequenceNumber(ClipboardType /* type */) const { |
DCHECK(CalledOnValidThread()); |
- // TODO: implement this. For now this interface will advertise |
- // that the clipboard never changes. That's fine as long as we |
- // don't rely on this signal. |
- return 0; |
+ return g_map.Get().GetSequenceNumber(); |
} |
bool ClipboardAndroid::IsFormatAvailable(const Clipboard::FormatType& format, |
@@ -414,10 +431,14 @@ void ClipboardAndroid::ReadData(const Clipboard::FormatType& format, |
*result = g_map.Get().Get(format.ToString()); |
} |
-base::Time ClipboardAndroid::GetClipboardLastModifiedTime() const { |
+base::Time ClipboardAndroid::GetLastModifiedTime() const { |
+ DCHECK(CalledOnValidThread()); |
+ return g_map.Get().GetLastModifiedTime(); |
+} |
+ |
+void ClipboardAndroid::ClearLastModifiedTime() { |
DCHECK(CalledOnValidThread()); |
- return base::Time::FromJavaTime( |
- g_map.Get().GetLastClipboardChangeTimeInMillis()); |
+ g_map.Get().ClearLastModifiedTime(); |
} |
// Main entry point used to write several values in the clipboard. |
@@ -485,4 +506,14 @@ void ClipboardAndroid::WriteData(const Clipboard::FormatType& format, |
g_map.Get().Set(format.ToString(), std::string(data_data, data_len)); |
} |
+bool RegisterClipboardAndroid(JNIEnv* env) { |
+ return RegisterNativesImpl(env); |
+} |
+ |
+// Returns a pointer to the current ClipboardAndroid object. |
+static jlong Init(JNIEnv* env, |
+ const base::android::JavaParamRef<jobject>& obj) { |
+ return reinterpret_cast<intptr_t>(Clipboard::GetForCurrentThread()); |
+} |
+ |
} // namespace ui |