Chromium Code Reviews| 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..7e2fce29ccd1f0e38dd297e061abecb575ca8bba 100644 |
| --- a/ui/base/clipboard/clipboard_android.cc |
| +++ b/ui/base/clipboard/clipboard_android.cc |
| @@ -8,10 +8,13 @@ |
| #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 "components/prefs/pref_registry_simple.h" |
| #include "jni/Clipboard_jni.h" |
| #include "third_party/skia/include/core/SkBitmap.h" |
| #include "ui/gfx/geometry/size.h" |
| @@ -37,6 +40,9 @@ using base::android::ScopedJavaLocalRef; |
| namespace ui { |
| namespace { |
| + |
| +const char kClipboardLastModifiedTimePref[] = "ui.clipboard.last_modified_time"; |
| + |
| // Various formats we support. |
| const char kURLFormat[] = "url"; |
| const char kPlainTextFormat[] = "text"; |
| @@ -50,18 +56,23 @@ class ClipboardMap { |
| public: |
| ClipboardMap(); |
| std::string Get(const std::string& format); |
| - int64_t GetLastClipboardChangeTimeInMillis(); |
| + uint64_t GetSequenceNumber() const; |
| + base::Time GetClipboardLastModifiedTime() const; |
| + void ClearClipboardLastModifiedTime(); |
|
dcheng
2017/04/12 00:56:09
Ditto: omit Clipboard in the names here.
Mark P
2017/04/12 21:33:51
Done.
|
| bool HasFormat(const std::string& format); |
| + void OnPrimaryClipboardChanged(); |
| void Set(const std::string& format, const std::string& data); |
| void CommitToAndroidClipboard(); |
| void Clear(); |
| private: |
| void UpdateFromAndroidClipboard(); |
| + void UpdateLastModifiedTimePref(); |
| std::map<std::string, std::string> map_; |
| base::Lock lock_; |
| - int64_t last_clipboard_change_time_ms_; |
| + uint64_t sequence_number_; |
| + base::Time clipboard_last_modified_time_; |
|
dcheng
2017/04/12 00:56:09
Nit: no clipboard_
Mark P
2017/04/12 21:33:51
Done.
|
| // Java class and methods for the Android ClipboardManager. |
| ScopedJavaGlobalRef<jobject> clipboard_manager_; |
| @@ -71,27 +82,44 @@ base::LazyInstance<ClipboardMap>::Leaky g_map = LAZY_INSTANCE_INITIALIZER; |
| ClipboardMap::ClipboardMap() { |
| clipboard_manager_.Reset(Java_Clipboard_getInstance(AttachCurrentThread())); |
| DCHECK(clipboard_manager_.obj()); |
| + UpdateFromAndroidClipboard(); |
| + // *** |
| + // Read |clipboard_last_modified_time_| as a time (in seconds) from prefs |
| + // under name |kClipboardLastModifiedTimePref|. Use 0 if the pref doesn't |
| + // exist. |
| } |
| std::string ClipboardMap::Get(const std::string& format) { |
| base::AutoLock lock(lock_); |
| - UpdateFromAndroidClipboard(); |
| std::map<std::string, std::string>::const_iterator it = map_.find(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::GetClipboardLastModifiedTime() const { |
| + return clipboard_last_modified_time_; |
| +} |
| + |
| +void ClipboardMap::ClearClipboardLastModifiedTime() { |
| + clipboard_last_modified_time_ = base::Time(); |
| + UpdateLastModifiedTimePref(); |
| } |
| bool ClipboardMap::HasFormat(const std::string& format) { |
| base::AutoLock lock(lock_); |
| - UpdateFromAndroidClipboard(); |
| return base::ContainsKey(map_, format); |
| } |
| +void ClipboardMap::OnPrimaryClipboardChanged() { |
| + sequence_number_++; |
| + clipboard_last_modified_time_ = base::Time::Now(); |
| + UpdateLastModifiedTimePref(); |
| + UpdateFromAndroidClipboard(); |
|
dcheng
2017/04/12 00:56:09
I do wonder if we want to do this work up-front wh
Mark P
2017/04/12 04:21:11
Sure, I think I can do that pretty cleanly.
I'll m
Mark P
2017/04/12 21:33:51
Done.
|
| +} |
| + |
| void ClipboardMap::Set(const std::string& format, const std::string& data) { |
| base::AutoLock lock(lock_); |
| map_[format] = data; |
| @@ -122,6 +150,9 @@ void ClipboardMap::CommitToAndroidClipboard() { |
| Java_Clipboard_clear(env, clipboard_manager_); |
| NOTIMPLEMENTED(); |
| } |
| + sequence_number_++; |
| + clipboard_last_modified_time_ = base::Time::Now(); |
| + UpdateLastModifiedTimePref(); |
| } |
| void ClipboardMap::Clear() { |
| @@ -129,6 +160,9 @@ void ClipboardMap::Clear() { |
| base::AutoLock lock(lock_); |
| map_.clear(); |
| Java_Clipboard_clear(env, clipboard_manager_); |
| + sequence_number_++; |
| + clipboard_last_modified_time_ = base::Time::Now(); |
| + UpdateLastModifiedTimePref(); |
| } |
| // Add a key:jstr pair to map, but only if jstr is not null, and also |
| @@ -144,38 +178,25 @@ 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. |
| + // 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_); |
| +void ClipboardMap::UpdateLastModifiedTimePref() { |
| + // *** |
| + // Record |clipboard_last_modified_time_| as a time (in seconds) to prefs |
| + // under name |kClipboardLastModifiedTimePref|. Make sure that null times |
| + // get recorded as 0. |
| } |
| } // namespace |
| @@ -277,6 +298,18 @@ Clipboard* Clipboard::Create() { |
| } |
| // ClipboardAndroid implementation. |
| + |
| +// static |
| +void ClipboardAndroid::RegisterPrefs(PrefRegistrySimple* registry) { |
| + registry->RegisterUint64Pref(kClipboardLastModifiedTimePref, 0u); |
| +} |
| + |
| +void ClipboardAndroid::OnPrimaryClipChanged( |
| + JNIEnv* env, |
| + const base::android::JavaParamRef<jobject>& obj) { |
| + g_map.Get().OnPrimaryClipboardChanged(); |
| +} |
| + |
| ClipboardAndroid::ClipboardAndroid() { |
| DCHECK(CalledOnValidThread()); |
| } |
| @@ -289,10 +322,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, |
| @@ -416,8 +446,12 @@ void ClipboardAndroid::ReadData(const Clipboard::FormatType& format, |
| base::Time ClipboardAndroid::GetClipboardLastModifiedTime() const { |
| DCHECK(CalledOnValidThread()); |
| - return base::Time::FromJavaTime( |
| - g_map.Get().GetLastClipboardChangeTimeInMillis()); |
| + return g_map.Get().GetClipboardLastModifiedTime(); |
| +} |
| + |
| +void ClipboardAndroid::ClearClipboardLastModifiedTime() { |
| + DCHECK(CalledOnValidThread()); |
| + g_map.Get().ClearClipboardLastModifiedTime(); |
| } |
| // Main entry point used to write several values in the clipboard. |
| @@ -485,4 +519,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 |