summaryrefslogtreecommitdiff
path: root/chromium/ui/base/clipboard
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/ui/base/clipboard')
-rw-r--r--chromium/ui/base/clipboard/BUILD.gn1
-rw-r--r--chromium/ui/base/clipboard/DIR_METADATA4
-rw-r--r--chromium/ui/base/clipboard/OWNERS5
-rw-r--r--chromium/ui/base/clipboard/README.md29
-rw-r--r--chromium/ui/base/clipboard/clipboard.cc35
-rw-r--r--chromium/ui/base/clipboard/clipboard.h57
-rw-r--r--chromium/ui/base/clipboard/clipboard_android.cc262
-rw-r--r--chromium/ui/base/clipboard/clipboard_android.h16
-rw-r--r--chromium/ui/base/clipboard/clipboard_android_test_support.cc8
-rw-r--r--chromium/ui/base/clipboard/clipboard_data.cc25
-rw-r--r--chromium/ui/base/clipboard/clipboard_data.h5
-rw-r--r--chromium/ui/base/clipboard/clipboard_format_type.h73
-rw-r--r--chromium/ui/base/clipboard/clipboard_format_type_android.cc51
-rw-r--r--chromium/ui/base/clipboard/clipboard_format_type_aura.cc58
-rw-r--r--chromium/ui/base/clipboard/clipboard_format_type_mac.mm49
-rw-r--r--chromium/ui/base/clipboard/clipboard_format_type_win.cc200
-rw-r--r--chromium/ui/base/clipboard/clipboard_mac.h38
-rw-r--r--chromium/ui/base/clipboard/clipboard_mac.mm140
-rw-r--r--chromium/ui/base/clipboard/clipboard_mac_unittest.mm88
-rw-r--r--chromium/ui/base/clipboard/clipboard_monitor.h6
-rw-r--r--chromium/ui/base/clipboard/clipboard_non_backed.cc115
-rw-r--r--chromium/ui/base/clipboard/clipboard_non_backed.h14
-rw-r--r--chromium/ui/base/clipboard/clipboard_non_backed_unittest.cc40
-rw-r--r--chromium/ui/base/clipboard/clipboard_ozone.cc67
-rw-r--r--chromium/ui/base/clipboard/clipboard_ozone.h19
-rw-r--r--chromium/ui/base/clipboard/clipboard_sequence_number_token.h19
-rw-r--r--chromium/ui/base/clipboard/clipboard_test_template.h400
-rw-r--r--chromium/ui/base/clipboard/clipboard_util_mac_unittest.mm34
-rw-r--r--chromium/ui/base/clipboard/clipboard_util_win.cc79
-rw-r--r--chromium/ui/base/clipboard/clipboard_win.cc182
-rw-r--r--chromium/ui/base/clipboard/clipboard_win.h23
-rw-r--r--chromium/ui/base/clipboard/clipboard_x11.cc89
-rw-r--r--chromium/ui/base/clipboard/clipboard_x11.h23
-rw-r--r--chromium/ui/base/clipboard/scoped_clipboard_writer.cc56
-rw-r--r--chromium/ui/base/clipboard/scoped_clipboard_writer.h11
35 files changed, 1473 insertions, 848 deletions
diff --git a/chromium/ui/base/clipboard/BUILD.gn b/chromium/ui/base/clipboard/BUILD.gn
index 42d2fb48145..52d88ba0ffb 100644
--- a/chromium/ui/base/clipboard/BUILD.gn
+++ b/chromium/ui/base/clipboard/BUILD.gn
@@ -78,6 +78,7 @@ component("clipboard") {
"clipboard_monitor.h",
"clipboard_observer.cc",
"clipboard_observer.h",
+ "clipboard_sequence_number_token.h",
"custom_data_helper.cc",
"custom_data_helper.h",
"scoped_clipboard_writer.cc",
diff --git a/chromium/ui/base/clipboard/DIR_METADATA b/chromium/ui/base/clipboard/DIR_METADATA
index 185817f957c..7d0a14efdc4 100644
--- a/chromium/ui/base/clipboard/DIR_METADATA
+++ b/chromium/ui/base/clipboard/DIR_METADATA
@@ -1,10 +1,10 @@
# Metadata information for this directory.
#
# For more information on DIR_METADATA files, see:
-# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md
+# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md
#
# For the schema of this file, see Metadata message:
-# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto
+# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto
monorail {
component: "Blink>DataTransfer"
diff --git a/chromium/ui/base/clipboard/OWNERS b/chromium/ui/base/clipboard/OWNERS
index 3520663eec7..894511c6deb 100644
--- a/chromium/ui/base/clipboard/OWNERS
+++ b/chromium/ui/base/clipboard/OWNERS
@@ -1,7 +1,8 @@
+asully@chromium.org
dcheng@chromium.org
-huangdarwin@chromium.org
+per-file clipboard_*android*=gangwu@chromium.org
+per-file clipboard_*mac*=avi@chromium.org
per-file clipboard_*ozone*=msisov@igalia.com
per-file clipboard_*ozone*=adunaev@igalia.com
per-file clipboard_*x11*=thomasanderson@chromium.org
-
diff --git a/chromium/ui/base/clipboard/README.md b/chromium/ui/base/clipboard/README.md
index 51d1a61b624..154b208122d 100644
--- a/chromium/ui/base/clipboard/README.md
+++ b/chromium/ui/base/clipboard/README.md
@@ -1,18 +1,43 @@
+# Browser Clipboard
+
Platform-neutral clipboard abstractions, to access platform-specific clipboards
(copy/paste) without platform-specific code.
+## Clipboard Model
+
+The clipboard can be thought of as an ordered dictionary keyed on format, with
+the value as the payload. This dictionary is implemented and accessed
+differently on different operating systems (OS’s).
+
+## Interfaces
+
Interfaces include:
* `Clipboard`: reading/pasting from the clipboard.
* `ScopedClipboardWriter`: writing/copying to the clipboard.
* `ClipboardObserver`: notifications of clipboard events.
* `ClipboardFormatType`: specifying clipboard formats.
+## Platform-specific behavior
+
While most platform-specific behavior should be abstracted away, some may
still be exposed. For some notable platform-specific behavior exposed by these
interfaces:
* `ClipboardAndroid` has a more limited set of supported formats.
* `ClipboardObserver` is only supported on some platforms, as other platforms
may require (inefficient) polling to implement.
-* `ClipboardX11` supports both the usual clipboard buffer, as well as the
- selection (middle-click) paste buffer.
+* Every platform may have different combinations of clipboard formats written,
+ or metadata written, for each clipboard format. For example, text in Windows
+ is written with a carriage return accompanying newlines, and in Linux requires
+ multiple MIME types to represent.
+* `ClipboardX11` supports both the usual clipboard buffer (CLIPBOARD selection),
+ as well as the middle-click paste buffer (PRIMARY selection). X11 selections
+ are documented in more detail in
+ [X11 documentation](https://tronche.com/gui/x/icccm/sec-2.html#s-2.6.1).
* `DataTransferPolicyController` is only currently exercised in ChromeOS.
+* `ClipboardWin` and `ClipboardX11` have limits to the amount of registered
+ clipboard formats. Windows has the smallest limit on the number of formats, at
+ [16384](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-registerclipboardformata#remarks),
+ and explored in
+ [this article](https://devblogs.microsoft.com/oldnewthing/20150319-00/?p=44433).
+ After these system resources are exhausted, the underlying OS may be rendered
+ unusable. \ No newline at end of file
diff --git a/chromium/ui/base/clipboard/clipboard.cc b/chromium/ui/base/clipboard/clipboard.cc
index e5aa1deb231..1916e5c82b9 100644
--- a/chromium/ui/base/clipboard/clipboard.cc
+++ b/chromium/ui/base/clipboard/clipboard.cc
@@ -10,6 +10,7 @@
#include "base/check.h"
#include "base/containers/contains.h"
+#include "base/json/json_reader.h"
#include "base/memory/ptr_util.h"
#include "base/notreached.h"
#include "third_party/skia/include/core/SkBitmap.h"
@@ -137,6 +138,33 @@ base::Time Clipboard::GetLastModifiedTime() const {
void Clipboard::ClearLastModifiedTime() {}
+std::map<std::string, std::string> Clipboard::ExtractCustomPlatformNames(
+ ClipboardBuffer buffer,
+ const DataTransferEndpoint* data_dst) const {
+ // Read the JSON metadata payload.
+ std::map<std::string, std::string> custom_format_names;
+ if (IsFormatAvailable(ui::ClipboardFormatType::WebCustomFormatMap(), buffer,
+ data_dst)) {
+ std::string custom_format_json;
+ // Read the custom format map.
+ ReadData(ui::ClipboardFormatType::WebCustomFormatMap(), data_dst,
+ &custom_format_json);
+ if (!custom_format_json.empty()) {
+ absl::optional<base::Value> json_val =
+ base::JSONReader::Read(custom_format_json);
+ if (json_val.has_value()) {
+ for (const auto it : json_val->DictItems()) {
+ std::string custom_format_name;
+ if (it.second.GetAsString(&custom_format_name)) {
+ custom_format_names.emplace(it.first, custom_format_name);
+ }
+ }
+ }
+ }
+ }
+ return custom_format_names;
+}
+
Clipboard::Clipboard() = default;
Clipboard::~Clipboard() = default;
@@ -203,6 +231,11 @@ void Clipboard::DispatchPortableRepresentation(PortableFormat format,
&(params[1].front()), params[1].size());
break;
+ case PortableFormat::kWebCustomFormatMap:
+ WriteData(ClipboardFormatType::WebCustomFormatMap(),
+ &(params[0].front()), params[0].size());
+ break;
+
default:
NOTREACHED();
}
@@ -211,7 +244,7 @@ void Clipboard::DispatchPortableRepresentation(PortableFormat format,
void Clipboard::DispatchPlatformRepresentations(
std::vector<Clipboard::PlatformRepresentation> platform_representations) {
for (const auto& representation : platform_representations) {
- WriteData(ClipboardFormatType::GetType(representation.format),
+ WriteData(ClipboardFormatType::CustomPlatformType(representation.format),
reinterpret_cast<const char*>(representation.data.data()),
representation.data.size());
}
diff --git a/chromium/ui/base/clipboard/clipboard.h b/chromium/ui/base/clipboard/clipboard.h
index 11ce126c3d8..85009c942b8 100644
--- a/chromium/ui/base/clipboard/clipboard.h
+++ b/chromium/ui/base/clipboard/clipboard.h
@@ -8,6 +8,7 @@
#include <stddef.h>
#include <stdint.h>
+#include <map>
#include <memory>
#include <string>
#include <vector>
@@ -16,8 +17,6 @@
#include "base/compiler_specific.h"
#include "base/component_export.h"
#include "base/containers/flat_map.h"
-#include "base/macros.h"
-#include "base/no_destructor.h"
#include "base/process/process.h"
#include "base/synchronization/lock.h"
#include "base/threading/platform_thread.h"
@@ -27,6 +26,7 @@
#include "mojo/public/cpp/base/big_buffer.h"
#include "ui/base/clipboard/clipboard_buffer.h"
#include "ui/base/clipboard/clipboard_format_type.h"
+#include "ui/base/clipboard/clipboard_sequence_number_token.h"
#include "ui/base/clipboard/file_info.h"
#include "ui/base/data_transfer_policy/data_transfer_endpoint.h"
@@ -69,6 +69,9 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) Clipboard
base::OnceCallback<void(std::u16string title, GURL url)>;
using ReadDataCallback = base::OnceCallback<void(std::string result)>;
+ Clipboard(const Clipboard&) = delete;
+ Clipboard& operator=(const Clipboard&) = delete;
+
static bool IsSupportedClipboardBuffer(ClipboardBuffer buffer);
// Sets the list of threads that are allowed to access the clipboard.
@@ -90,6 +93,8 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) Clipboard
// the main UI thread, but Windows has tricky semantics where there have to
// be two clipboards: one that lives on the UI thread and one that lives on
// the IO thread.
+ //
+ // The return value should not be cached.
static Clipboard* GetForCurrentThread();
// Removes and transfers ownership of the current thread's clipboard to the
@@ -114,10 +119,11 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) Clipboard
virtual const DataTransferEndpoint* GetSource(
ClipboardBuffer buffer) const = 0;
- // Returns a sequence number which uniquely identifies clipboard state.
- // This can be used to version the data on the clipboard and determine
- // whether it has changed.
- virtual uint64_t GetSequenceNumber(ClipboardBuffer buffer) const = 0;
+ // Returns a token which uniquely identifies clipboard state.
+ // ClipboardSequenceNumberTokens are used since there may be multiple
+ // ui::Clipboard instances that have the same sequence number.
+ virtual const ClipboardSequenceNumberToken& GetSequenceNumber(
+ ClipboardBuffer buffer) const = 0;
// Tests whether the clipboard contains a certain format.
virtual bool IsFormatAvailable(
@@ -207,7 +213,7 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) Clipboard
virtual void ReadBookmark(const DataTransferEndpoint* data_dst,
ReadBookmarkCallback callback) const;
- // Reads raw data from the clipboard with the given format type. Stores result
+ // Reads data from the clipboard with the given format type. Stores result
// as a byte vector.
virtual void ReadData(const ClipboardFormatType& format,
const DataTransferEndpoint* data_dst,
@@ -260,13 +266,22 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) Clipboard
// Resets the clipboard last modified time to Time::Time().
virtual void ClearLastModifiedTime();
+ // Reads the web custom format map (which is in JSON format) from the
+ // clipboard if it's available. Parses the JSON string that has the mapping of
+ // MIME type to custom format name and fetches the list of custom MIME types.
+ // e.g. on Windows, the mapping is represented as "text/html":"Web Custom
+ // Format(0-99)".
+ std::map<std::string, std::string> ExtractCustomPlatformNames(
+ ClipboardBuffer buffer,
+ const DataTransferEndpoint* data_dst) const;
+
protected:
// PortableFormat designates the type of data to be stored in the clipboard.
// This designation is shared across all OSes. The system-specific designation
// is defined by ClipboardFormatType. A single PortableFormat might be
// represented by several system-specific ClipboardFormatTypes. For example,
// on Linux the kText PortableFormat maps to "text/plain", "STRING", and
- // several other formats. On windows it maps to CF_UNICODETEXT.
+ // several other formats. On Windows it maps to CF_UNICODETEXT.
//
// The order below is the order in which data will be written to the
// clipboard, so more specific types must be listed before less specific
@@ -274,6 +289,8 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) Clipboard
// clipboard to contain a bitmap, HTML markup representing the image, a URL to
// the image, and the image's alt text. Having the types follow this order
// maximizes the amount of data that can be extracted by various programs.
+ // Documentation on motivation for format ordering is also available here:
+ // https://docs.microsoft.com/en-us/windows/win32/dataxchg/clipboard-formats#multiple-clipboard-formats
enum class PortableFormat {
kBitmap, // Bitmap from shared memory.
kHtml,
@@ -284,6 +301,7 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) Clipboard
kData, // Arbitrary block of bytes.
kSvg,
kFilenames,
+ kWebCustomFormatMap,
};
// TODO (https://crbug.com/994928): Rename ObjectMap-related types.
@@ -307,6 +325,7 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) Clipboard
// kWebkit none empty vector
// kData format char array
// data byte array
+ // kWebCustomFormatMap char array
using ObjectMapParam = std::vector<char>;
using ObjectMapParams = std::vector<ObjectMapParam>;
using ObjectMap = base::flat_map<PortableFormat, ObjectMapParams>;
@@ -328,22 +347,14 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) Clipboard
Clipboard();
virtual ~Clipboard();
- // Write a bunch of objects to the system clipboard. Copies are made of the
- // contents of |objects|. Also, adds the source of the data to the clipboard,
- // which can be used when we need to restrict the clipboard data between a set
- // of confidential documents. The data source maybe passed as nullptr.
- virtual void WritePortableRepresentations(
+ // Write platform & portable formats, in the order of their appearance in
+ // `platform_representations` & `ObjectMap`. Also, adds the source of the data
+ // to the clipboard, which can be used when we need to restrict the clipboard
+ // data between a set of confidential documents. The data source maybe passed
+ // as nullptr.
+ virtual void WritePortableAndPlatformRepresentations(
ClipboardBuffer buffer,
const ObjectMap& objects,
- std::unique_ptr<DataTransferEndpoint> data_src) = 0;
-
- // Write |platform_representations|, in the order of their appearance in
- // |platform_representations|. Also, adds the source of the data to the
- // clipboard, which can be used when we need to restrict the clipboard data
- // between a set of confidential documents. The data source maybe passed as
- // nullptr.
- virtual void WritePlatformRepresentations(
- ClipboardBuffer buffer,
std::vector<Clipboard::PlatformRepresentation> platform_representations,
std::unique_ptr<DataTransferEndpoint> data_src) = 0;
@@ -411,8 +422,6 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) Clipboard
// Mutex that controls access to |g_clipboard_map|.
static base::Lock& ClipboardMapLock();
-
- DISALLOW_COPY_AND_ASSIGN(Clipboard);
};
} // namespace ui
diff --git a/chromium/ui/base/clipboard/clipboard_android.cc b/chromium/ui/base/clipboard/clipboard_android.cc
index 62e6ef76ac2..3460fd1d40e 100644
--- a/chromium/ui/base/clipboard/clipboard_android.cc
+++ b/chromium/ui/base/clipboard/clipboard_android.cc
@@ -5,6 +5,7 @@
#include "ui/base/clipboard/clipboard_android.h"
#include <algorithm>
+#include <cstdint>
#include <map>
#include <string>
#include <utility>
@@ -32,6 +33,7 @@
#include "ui/base/data_transfer_policy/data_transfer_endpoint.h"
#include "ui/base/ui_base_jni_headers/Clipboard_jni.h"
#include "ui/gfx/android/java_bitmap.h"
+#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/image/image.h"
// TODO:(andrewhayden) Support additional formats in Android: URI, HTML,
@@ -67,6 +69,22 @@ constexpr char kPngExtension[] = ".png";
using ReadPngCallback = ClipboardAndroid::ReadPngCallback;
using ReadImageCallback = ClipboardAndroid::ReadImageCallback;
+// Fetching image data from Java as PNG bytes.
+std::vector<uint8_t> GetPngData(
+ const base::android::ScopedJavaGlobalRef<jobject>& clipboard_manager) {
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jbyteArray> jimage_data =
+ Java_Clipboard_getPng(env, clipboard_manager);
+ if (jimage_data.is_null()) {
+ return std::vector<uint8_t>();
+ }
+ DCHECK(jimage_data.obj());
+
+ std::vector<uint8_t> png_data;
+ JavaByteArrayToByteVector(env, jimage_data, &png_data);
+ return png_data;
+}
+
// Fetching image data from Java.
SkBitmap GetImageData(
const base::android::ScopedJavaGlobalRef<jobject>& clipboard_manager) {
@@ -86,14 +104,36 @@ SkBitmap GetImageData(
return gfx::CreateSkBitmapFromJavaBitmap(java_bitmap);
}
+// Add a format:jstr pair to map, if jstr is null or is empty, then remove that
+// entry.
+void JNI_Clipboard_AddMapEntry(JNIEnv* env,
+ std::map<ClipboardFormatType, std::string>* map,
+ const ClipboardFormatType& format,
+ const ScopedJavaLocalRef<jstring>& jstr) {
+ if (jstr.is_null()) {
+ map->erase(format);
+ return;
+ }
+
+ std::string str = ConvertJavaStringToUTF8(env, jstr.obj());
+ if (!str.empty()) {
+ (*map)[format] = str;
+ } else {
+ map->erase(format);
+ }
+}
+
class ClipboardMap {
public:
ClipboardMap();
void SetModifiedCallback(ClipboardAndroid::ModifiedCallback cb);
void SetJavaSideNativePtr(Clipboard* clipboard);
std::string Get(const ClipboardFormatType& format);
+ void GetPng(ReadPngCallback callback);
void GetImage(ReadImageCallback callback);
- uint64_t GetSequenceNumber() const;
+ void DidGetPng(ReadPngCallback callback, std::vector<uint8_t> result);
+ void DidGetImage(ReadImageCallback callback, const SkBitmap& result);
+ const ClipboardSequenceNumberToken& GetSequenceNumber() const;
base::Time GetLastModifiedTime() const;
void ClearLastModifiedTime();
bool HasFormat(const ClipboardFormatType& format);
@@ -130,7 +170,7 @@ class ClipboardMap {
// This lock is for read/write |map_|.
base::Lock lock_;
- uint64_t sequence_number_;
+ ClipboardSequenceNumberToken sequence_number_;
base::Time last_modified_time_;
ClipboardAndroid::ModifiedCallback modified_cb_;
@@ -162,13 +202,65 @@ std::string ClipboardMap::Get(const ClipboardFormatType& format) {
return it == map_.end() ? std::string() : it->second;
}
+void ClipboardMap::GetPng(ReadPngCallback callback) {
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
+ base::BindOnce(&GetPngData, clipboard_manager_),
+ base::BindOnce(&ClipboardMap::DidGetPng, base::Unretained(this),
+ std::move(callback)));
+}
+
void ClipboardMap::GetImage(ReadImageCallback callback) {
base::ThreadPool::PostTaskAndReplyWithResult(
FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
- base::BindOnce(&GetImageData, clipboard_manager_), std::move(callback));
+ base::BindOnce(&GetImageData, clipboard_manager_),
+ base::BindOnce(&ClipboardMap::DidGetImage, base::Unretained(this),
+ std::move(callback)));
+}
+
+void ClipboardMap::DidGetPng(ReadPngCallback callback,
+ std::vector<uint8_t> result) {
+ // GetPngData attempts to read from the Java Clipboard, which sometimes is
+ // not available (ex. the app is not in focus, such as in unit tests).
+ if (!result.empty()) {
+ std::move(callback).Run(std::move(result));
+ return;
+ }
+
+ // Since the The Java Clipboard did not provide a valid bitmap, attempt to
+ // read from our in-memory clipboard map if the map is up-to-date.
+ if (map_state_ != MapState::kUpToDate) {
+ std::move(callback).Run(std::vector<uint8_t>());
+ return;
+ }
+ std::string png_str = g_map.Get().Get(ClipboardFormatType::PngType());
+ std::vector<uint8_t> png_data{png_str.begin(), png_str.end()};
+ std::move(callback).Run(png_data);
+}
+
+void ClipboardMap::DidGetImage(ReadImageCallback callback,
+ const SkBitmap& result) {
+ // GetImageData attempts to read from the Java Clipboard, which sometimes is
+ // not available (ex. the app is not in focus, such as in unit tests).
+ if (!result.isNull()) {
+ std::move(callback).Run(std::move(result));
+ return;
+ }
+
+ // Since the The Java Clipboard did not provide a valid bitmap, attempt to
+ // read from our in-memory clipboard map if the map is up-to-date.
+ if (map_state_ != MapState::kUpToDate) {
+ std::move(callback).Run(SkBitmap());
+ return;
+ }
+ std::string png_str = g_map.Get().Get(ClipboardFormatType::PngType());
+ SkBitmap bitmap;
+ gfx::PNGCodec::Decode(reinterpret_cast<const unsigned char*>(png_str.data()),
+ png_str.size(), &bitmap);
+ std::move(callback).Run(std::move(bitmap));
}
-uint64_t ClipboardMap::GetSequenceNumber() const {
+const ClipboardSequenceNumberToken& ClipboardMap::GetSequenceNumber() const {
return sequence_number_;
}
@@ -184,6 +276,12 @@ bool ClipboardMap::HasFormat(const ClipboardFormatType& format) {
base::AutoLock lock(lock_);
if (map_state_ == MapState::kUpToDate) {
// If the 'map_' is up to date, we can just check with it.
+ // Images can be read if either bitmap or PNG types are available.
+ if (format == ClipboardFormatType::PngType() ||
+ format == ClipboardFormatType::BitmapType()) {
+ return base::Contains(map_, ClipboardFormatType::PngType()) ||
+ base::Contains(map_, ClipboardFormatType::BitmapType());
+ }
return base::Contains(map_, format);
}
@@ -195,13 +293,14 @@ bool ClipboardMap::HasFormat(const ClipboardFormatType& format) {
// up.
JNIEnv* env = AttachCurrentThread();
// TODO(crbug.com/1194601): Create a single method for the follow JNI calls.
- if (format == ClipboardFormatType::GetPlainTextType()) {
+ if (format == ClipboardFormatType::PlainTextType()) {
return Java_Clipboard_hasCoercedText(env, clipboard_manager_);
- } else if (format == ClipboardFormatType::GetHtmlType()) {
+ } else if (format == ClipboardFormatType::HtmlType()) {
return Java_Clipboard_hasHTMLOrStyledText(env, clipboard_manager_);
- } else if (format == ClipboardFormatType::GetUrlType()) {
+ } else if (format == ClipboardFormatType::UrlType()) {
return Java_Clipboard_hasUrl(env, clipboard_manager_);
- } else if (format == ClipboardFormatType::GetType(kMimeTypeImageURI)) {
+ } else if (format == ClipboardFormatType::PngType() ||
+ format == ClipboardFormatType::BitmapType()) {
return Java_Clipboard_hasImage(env, clipboard_manager_);
}
@@ -218,16 +317,17 @@ std::vector<ClipboardFormatType> ClipboardMap::GetFormats() {
if (map_state_ != MapState::kUpToDate) {
JNIEnv* env = AttachCurrentThread();
if (Java_Clipboard_hasCoercedText(env, clipboard_manager_)) {
- formats.push_back(ClipboardFormatType::GetPlainTextType());
+ formats.push_back(ClipboardFormatType::PlainTextType());
}
if (Java_Clipboard_hasHTMLOrStyledText(env, clipboard_manager_)) {
- formats.push_back(ClipboardFormatType::GetHtmlType());
+ formats.push_back(ClipboardFormatType::HtmlType());
}
if (Java_Clipboard_hasUrl(env, clipboard_manager_)) {
- formats.push_back(ClipboardFormatType::GetUrlType());
+ formats.push_back(ClipboardFormatType::UrlType());
}
if (Java_Clipboard_hasImage(env, clipboard_manager_)) {
- formats.push_back(ClipboardFormatType::GetBitmapType());
+ formats.push_back(ClipboardFormatType::BitmapType());
+ formats.push_back(ClipboardFormatType::PngType());
}
}
@@ -235,10 +335,11 @@ std::vector<ClipboardFormatType> ClipboardMap::GetFormats() {
// not synced on any other layer.
for (const auto& it : map_) {
if (map_state_ != MapState::kUpToDate &&
- (it.first == ClipboardFormatType::GetPlainTextType() ||
- it.first == ClipboardFormatType::GetHtmlType() ||
- it.first == ClipboardFormatType::GetUrlType() ||
- it.first == ClipboardFormatType::GetType(kMimeTypeImageURI))) {
+ (it.first == ClipboardFormatType::PlainTextType() ||
+ it.first == ClipboardFormatType::HtmlType() ||
+ it.first == ClipboardFormatType::UrlType() ||
+ it.first == ClipboardFormatType::BitmapType() ||
+ it.first == ClipboardFormatType::PngType())) {
continue;
}
formats.push_back(it.first);
@@ -248,7 +349,7 @@ std::vector<ClipboardFormatType> ClipboardMap::GetFormats() {
}
void ClipboardMap::OnPrimaryClipboardChanged() {
- sequence_number_++;
+ sequence_number_ = ClipboardSequenceNumberToken();
UpdateLastModifiedTime(base::Time::Now());
map_state_ = MapState::kOutOfDate;
}
@@ -256,7 +357,7 @@ void ClipboardMap::OnPrimaryClipboardChanged() {
void ClipboardMap::OnPrimaryClipTimestampInvalidated(int64_t timestamp_ms) {
base::Time timestamp = base::Time::FromJavaTime(timestamp_ms);
if (GetLastModifiedTime() < timestamp) {
- sequence_number_++;
+ sequence_number_ = ClipboardSequenceNumberToken();
UpdateLastModifiedTime(timestamp);
map_state_ = MapState::kOutOfDate;
}
@@ -272,39 +373,46 @@ void ClipboardMap::Set(const ClipboardFormatType& format,
void ClipboardMap::CommitToAndroidClipboard() {
JNIEnv* env = AttachCurrentThread();
base::AutoLock lock(lock_);
- if (base::Contains(map_, ClipboardFormatType::GetHtmlType())) {
+ if (base::Contains(map_, ClipboardFormatType::HtmlType())) {
// Android's API for storing HTML content on the clipboard requires a plain-
// text representation to be available as well.
- if (!base::Contains(map_, ClipboardFormatType::GetPlainTextType()))
+ if (!base::Contains(map_, ClipboardFormatType::PlainTextType()))
return;
ScopedJavaLocalRef<jstring> html =
- ConvertUTF8ToJavaString(env, map_[ClipboardFormatType::GetHtmlType()]);
+ ConvertUTF8ToJavaString(env, map_[ClipboardFormatType::HtmlType()]);
ScopedJavaLocalRef<jstring> text = ConvertUTF8ToJavaString(
- env, map_[ClipboardFormatType::GetPlainTextType()]);
+ env, map_[ClipboardFormatType::PlainTextType()]);
DCHECK(html.obj() && text.obj());
Java_Clipboard_setHTMLText(env, clipboard_manager_, html, text);
- } else if (base::Contains(map_, ClipboardFormatType::GetPlainTextType())) {
+ } else if (base::Contains(map_, ClipboardFormatType::PlainTextType())) {
ScopedJavaLocalRef<jstring> str = ConvertUTF8ToJavaString(
- env, map_[ClipboardFormatType::GetPlainTextType()]);
+ env, map_[ClipboardFormatType::PlainTextType()]);
DCHECK(str.obj());
Java_Clipboard_setText(env, clipboard_manager_, str);
- } else if (base::Contains(map_, ClipboardFormatType::GetBitmapType())) {
+ } else if (base::Contains(map_, ClipboardFormatType::PngType())) {
+ // Committing the PNG data to the Android clipboard will create an image
+ // with a corresponding URI. Once this has been created, update the local
+ // clipboard with this URI.
ScopedJavaLocalRef<jbyteArray> image_data =
- ToJavaByteArray(env, map_[ClipboardFormatType::GetBitmapType()]);
+ ToJavaByteArray(env, map_[ClipboardFormatType::PngType()]);
ScopedJavaLocalRef<jstring> image_extension =
ConvertUTF8ToJavaString(env, kPngExtension);
DCHECK(image_data.obj());
+ // TODO(crbug.com/1223215) In unit tests, `jimageuri` is empty.
Java_Clipboard_setImage(env, clipboard_manager_, image_data,
image_extension);
+ ScopedJavaLocalRef<jstring> jimageuri =
+ Java_Clipboard_getImageUriString(env, clipboard_manager_);
+ JNI_Clipboard_AddMapEntry(env, &map_, ClipboardFormatType::BitmapType(),
+ jimageuri);
} else {
Java_Clipboard_clear(env, clipboard_manager_);
- // TODO(huangdarwin): Implement raw clipboard support for arbitrary formats.
NOTIMPLEMENTED();
}
map_state_ = MapState::kUpToDate;
- sequence_number_++;
+ sequence_number_ = ClipboardSequenceNumberToken();
UpdateLastModifiedTime(base::Time::Now());
}
@@ -314,7 +422,7 @@ void ClipboardMap::Clear() {
map_.clear();
Java_Clipboard_clear(env, clipboard_manager_);
map_state_ = MapState::kUpToDate;
- sequence_number_++;
+ sequence_number_ = ClipboardSequenceNumberToken();
UpdateLastModifiedTime(base::Time::Now());
}
@@ -322,25 +430,6 @@ void ClipboardMap::SetLastModifiedTimeWithoutRunningCallback(base::Time time) {
last_modified_time_ = time;
}
-// Add a format:jstr pair to map, if jstr is null or is empty, then remove that
-// entry.
-void JNI_Clipboard_AddMapEntry(JNIEnv* env,
- std::map<ClipboardFormatType, std::string>* map,
- const ClipboardFormatType& format,
- const ScopedJavaLocalRef<jstring>& jstr) {
- if (jstr.is_null()) {
- map->erase(format);
- return;
- }
-
- std::string str = ConvertJavaStringToUTF8(env, jstr.obj());
- if (!str.empty()) {
- (*map)[format] = str;
- } else {
- map->erase(format);
- }
-}
-
void ClipboardMap::UpdateLastModifiedTime(base::Time time) {
last_modified_time_ = time;
// |modified_cb_| may be null in tests.
@@ -366,14 +455,12 @@ void ClipboardMap::UpdateFromAndroidClipboard() {
ScopedJavaLocalRef<jstring> jimageuri =
Java_Clipboard_getImageUriString(env, clipboard_manager_);
- JNI_Clipboard_AddMapEntry(env, &map_, ClipboardFormatType::GetPlainTextType(),
+ JNI_Clipboard_AddMapEntry(env, &map_, ClipboardFormatType::PlainTextType(),
jtext);
- JNI_Clipboard_AddMapEntry(env, &map_, ClipboardFormatType::GetHtmlType(),
- jhtml);
- JNI_Clipboard_AddMapEntry(env, &map_, ClipboardFormatType::GetUrlType(),
- jurl);
- JNI_Clipboard_AddMapEntry(
- env, &map_, ClipboardFormatType::GetType(kMimeTypeImageURI), jimageuri);
+ JNI_Clipboard_AddMapEntry(env, &map_, ClipboardFormatType::HtmlType(), jhtml);
+ JNI_Clipboard_AddMapEntry(env, &map_, ClipboardFormatType::UrlType(), jurl);
+ JNI_Clipboard_AddMapEntry(env, &map_, ClipboardFormatType::BitmapType(),
+ jimageuri);
map_state_ = MapState::kUpToDate;
}
@@ -433,7 +520,7 @@ DataTransferEndpoint* ClipboardAndroid::GetSource(
return nullptr;
}
-uint64_t ClipboardAndroid::GetSequenceNumber(
+const ClipboardSequenceNumberToken& ClipboardAndroid::GetSequenceNumber(
ClipboardBuffer /* buffer */) const {
DCHECK(CalledOnValidThread());
return g_map.Get().GetSequenceNumber();
@@ -447,11 +534,6 @@ bool ClipboardAndroid::IsFormatAvailable(
const DataTransferEndpoint* data_dst) const {
DCHECK(CalledOnValidThread());
DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
-
- if (format == ClipboardFormatType::GetBitmapType()) {
- return g_map.Get().HasFormat(
- ClipboardFormatType::GetType(kMimeTypeImageURI));
- }
return g_map.Get().HasFormat(format);
}
@@ -475,17 +557,20 @@ void ClipboardAndroid::ReadAvailableTypes(
// would be nice to ask the ClipboardMap to enumerate the types it supports,
// rather than hardcode the list here.
- if (IsFormatAvailable(ClipboardFormatType::GetPlainTextType(), buffer,
- data_dst))
+ if (IsFormatAvailable(ClipboardFormatType::PlainTextType(), buffer, data_dst))
types->push_back(base::UTF8ToUTF16(kMimeTypeText));
- if (IsFormatAvailable(ClipboardFormatType::GetHtmlType(), buffer, data_dst))
+ if (IsFormatAvailable(ClipboardFormatType::HtmlType(), buffer, data_dst))
types->push_back(base::UTF8ToUTF16(kMimeTypeHTML));
- if (IsFormatAvailable(ClipboardFormatType::GetBitmapType(), buffer, data_dst))
+ // We can read images from either the Android clipboard or the local map.
+ if (IsFormatAvailable(ClipboardFormatType::BitmapType(), buffer, data_dst) ||
+ IsFormatAvailable(ClipboardFormatType::PngType(), buffer, data_dst)) {
+ types->push_back(base::UTF8ToUTF16(kMimeTypeImageURI));
types->push_back(base::UTF8ToUTF16(kMimeTypePNG));
+ }
// these formats aren't supported by the ClipboardMap currently, but might
// be one day?
- if (IsFormatAvailable(ClipboardFormatType::GetRtfType(), buffer, data_dst))
+ if (IsFormatAvailable(ClipboardFormatType::RtfType(), buffer, data_dst))
types->push_back(base::UTF8ToUTF16(kMimeTypeRTF));
}
@@ -526,7 +611,7 @@ void ClipboardAndroid::ReadAsciiText(ClipboardBuffer buffer,
DCHECK(CalledOnValidThread());
DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
RecordRead(ClipboardFormatMetric::kText);
- *result = g_map.Get().Get(ClipboardFormatType::GetPlainTextType());
+ *result = g_map.Get().Get(ClipboardFormatType::PlainTextType());
}
// |src_url| isn't really used. It is only implemented in Windows.
@@ -544,7 +629,7 @@ void ClipboardAndroid::ReadHTML(ClipboardBuffer buffer,
if (src_url)
src_url->clear();
- std::string input = g_map.Get().Get(ClipboardFormatType::GetHtmlType());
+ std::string input = g_map.Get().Get(ClipboardFormatType::HtmlType());
*markup = base::UTF8ToUTF16(input);
*fragment_start = 0;
@@ -558,7 +643,7 @@ void ClipboardAndroid::ReadSvg(ClipboardBuffer buffer,
std::u16string* result) const {
DCHECK(CalledOnValidThread());
DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
- std::string utf8 = g_map.Get().Get(ClipboardFormatType::GetSvgType());
+ std::string utf8 = g_map.Get().Get(ClipboardFormatType::SvgType());
*result = base::UTF8ToUTF16(utf8);
}
@@ -577,8 +662,9 @@ void ClipboardAndroid::ReadPng(ClipboardBuffer buffer,
const DataTransferEndpoint* data_dst,
ReadPngCallback callback) const {
DCHECK(CalledOnValidThread());
- // TODO(crbug.com/1201018): Implement this.
- NOTIMPLEMENTED();
+ DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
+ RecordRead(ClipboardFormatMetric::kPng);
+ g_map.Get().GetPng(std::move(callback));
}
// |data_dst| is not used. It's only passed to be consistent with other
@@ -618,7 +704,7 @@ void ClipboardAndroid::ReadBookmark(const DataTransferEndpoint* data_dst,
std::string* url) const {
DCHECK(CalledOnValidThread());
RecordRead(ClipboardFormatMetric::kBookmark);
- *url = g_map.Get().Get(ClipboardFormatType::GetUrlType());
+ *url = g_map.Get().Get(ClipboardFormatType::UrlType());
}
// |data_dst| is not used. It's only passed to be consistent with other
@@ -644,24 +730,9 @@ void ClipboardAndroid::ClearLastModifiedTime() {
// Main entry point used to write several values in the clipboard.
// |data_src| is not used. It's only passed to be consistent with other
// platforms.
-void ClipboardAndroid::WritePortableRepresentations(
+void ClipboardAndroid::WritePortableAndPlatformRepresentations(
ClipboardBuffer buffer,
const ObjectMap& objects,
- std::unique_ptr<DataTransferEndpoint> data_src) {
- DCHECK(CalledOnValidThread());
- DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
- g_map.Get().Clear();
-
- for (const auto& object : objects)
- DispatchPortableRepresentation(object.first, object.second);
-
- g_map.Get().CommitToAndroidClipboard();
-}
-
-// |data_src| is not used. It's only passed to be consistent with other
-// platforms.
-void ClipboardAndroid::WritePlatformRepresentations(
- ClipboardBuffer buffer,
std::vector<Clipboard::PlatformRepresentation> platform_representations,
std::unique_ptr<DataTransferEndpoint> data_src) {
DCHECK(CalledOnValidThread());
@@ -669,12 +740,14 @@ void ClipboardAndroid::WritePlatformRepresentations(
g_map.Get().Clear();
DispatchPlatformRepresentations(std::move(platform_representations));
+ for (const auto& object : objects)
+ DispatchPortableRepresentation(object.first, object.second);
g_map.Get().CommitToAndroidClipboard();
}
void ClipboardAndroid::WriteText(const char* text_data, size_t text_len) {
- g_map.Get().Set(ClipboardFormatType::GetPlainTextType(),
+ g_map.Get().Set(ClipboardFormatType::PlainTextType(),
std::string(text_data, text_len));
}
@@ -682,12 +755,12 @@ void ClipboardAndroid::WriteHTML(const char* markup_data,
size_t markup_len,
const char* url_data,
size_t url_len) {
- g_map.Get().Set(ClipboardFormatType::GetHtmlType(),
+ g_map.Get().Set(ClipboardFormatType::HtmlType(),
std::string(markup_data, markup_len));
}
void ClipboardAndroid::WriteSvg(const char* markup_data, size_t markup_len) {
- g_map.Get().Set(ClipboardFormatType::GetSvgType(),
+ g_map.Get().Set(ClipboardFormatType::SvgType(),
std::string(markup_data, markup_len));
}
@@ -705,15 +778,14 @@ void ClipboardAndroid::WriteBookmark(const char* title_data,
size_t title_len,
const char* url_data,
size_t url_len) {
- g_map.Get().Set(ClipboardFormatType::GetUrlType(),
+ g_map.Get().Set(ClipboardFormatType::UrlType(),
std::string(url_data, url_len));
}
// Write an extra flavor that signifies WebKit was the last to modify the
// pasteboard. This flavor has no data.
void ClipboardAndroid::WriteWebSmartPaste() {
- g_map.Get().Set(ClipboardFormatType::GetWebKitSmartPasteType(),
- std::string());
+ g_map.Get().Set(ClipboardFormatType::WebKitSmartPasteType(), std::string());
}
// Encoding SkBitmap to PNG data. Then, |g_map| can commit the PNG data to
@@ -723,7 +795,7 @@ void ClipboardAndroid::WriteBitmap(const SkBitmap& sk_bitmap) {
gfx::Image::CreateFrom1xBitmap(sk_bitmap).As1xPNGBytes();
std::string packed(image_memory->front_as<char>(), image_memory->size());
- g_map.Get().Set(ClipboardFormatType::GetBitmapType(), packed);
+ g_map.Get().Set(ClipboardFormatType::PngType(), packed);
}
void ClipboardAndroid::WriteData(const ClipboardFormatType& format,
diff --git a/chromium/ui/base/clipboard/clipboard_android.h b/chromium/ui/base/clipboard/clipboard_android.h
index 870ee348b14..ee7865653c6 100644
--- a/chromium/ui/base/clipboard/clipboard_android.h
+++ b/chromium/ui/base/clipboard/clipboard_android.h
@@ -14,17 +14,21 @@
#include "base/android/scoped_java_ref.h"
#include "base/callback_forward.h"
#include "base/component_export.h"
-#include "base/macros.h"
#include "base/time/time.h"
namespace ui {
+// Documentation on the underlying Android API this ultimately abstracts is
+// available at https://developer.android.com/guide/topics/text/copy-paste.
class ClipboardAndroid : public Clipboard {
public:
// Callback called whenever the clipboard is modified. The parameter
// represents the time of the modification.
using ModifiedCallback = base::RepeatingCallback<void(base::Time)>;
+ ClipboardAndroid(const ClipboardAndroid&) = delete;
+ ClipboardAndroid& operator=(const ClipboardAndroid&) = delete;
+
// Called by Java when the Java Clipboard is notified that the clipboard has
// changed.
void OnPrimaryClipChanged(JNIEnv* env,
@@ -59,7 +63,8 @@ class ClipboardAndroid : public Clipboard {
// Clipboard overrides:
void OnPreShutdown() override;
DataTransferEndpoint* GetSource(ClipboardBuffer buffer) const override;
- uint64_t GetSequenceNumber(ClipboardBuffer buffer) const override;
+ const ClipboardSequenceNumberToken& GetSequenceNumber(
+ ClipboardBuffer buffer) const override;
bool IsFormatAvailable(const ClipboardFormatType& format,
ClipboardBuffer buffer,
const DataTransferEndpoint* data_dst) const override;
@@ -109,12 +114,9 @@ class ClipboardAndroid : public Clipboard {
std::string* result) const override;
base::Time GetLastModifiedTime() const override;
void ClearLastModifiedTime() override;
- void WritePortableRepresentations(
+ void WritePortableAndPlatformRepresentations(
ClipboardBuffer buffer,
const ObjectMap& objects,
- std::unique_ptr<DataTransferEndpoint> data_src) override;
- void WritePlatformRepresentations(
- ClipboardBuffer buffer,
std::vector<Clipboard::PlatformRepresentation> platform_representations,
std::unique_ptr<DataTransferEndpoint> data_src) override;
void WriteText(const char* text_data, size_t text_len) override;
@@ -134,8 +136,6 @@ class ClipboardAndroid : public Clipboard {
void WriteData(const ClipboardFormatType& format,
const char* data_data,
size_t data_len) override;
-
- DISALLOW_COPY_AND_ASSIGN(ClipboardAndroid);
};
} // namespace ui
diff --git a/chromium/ui/base/clipboard/clipboard_android_test_support.cc b/chromium/ui/base/clipboard/clipboard_android_test_support.cc
index b7f126afcfb..d821fdd28be 100644
--- a/chromium/ui/base/clipboard/clipboard_android_test_support.cc
+++ b/chromium/ui/base/clipboard/clipboard_android_test_support.cc
@@ -33,10 +33,10 @@ jboolean JNI_ClipboardAndroidTestSupport_NativeWriteHtml(
clipboard_writer.WriteText(html_text);
}
auto* clipboard = Clipboard::GetForCurrentThread();
- return clipboard->IsFormatAvailable(ClipboardFormatType::GetHtmlType(),
+ return clipboard->IsFormatAvailable(ClipboardFormatType::HtmlType(),
ClipboardBuffer::kCopyPaste,
/* data_dst = */ nullptr) &&
- clipboard->IsFormatAvailable(ClipboardFormatType::GetPlainTextType(),
+ clipboard->IsFormatAvailable(ClipboardFormatType::PlainTextType(),
ClipboardBuffer::kCopyPaste,
/* data_dst = */ nullptr);
}
@@ -48,14 +48,14 @@ jboolean JNI_ClipboardAndroidTestSupport_NativeClipboardContains(
// ClipboardManager. This should update the native side of the clipboard as
// well as the Android side.
auto* clipboard = Clipboard::GetForCurrentThread();
- if (clipboard->IsFormatAvailable(ClipboardFormatType::GetHtmlType(),
+ if (clipboard->IsFormatAvailable(ClipboardFormatType::HtmlType(),
ClipboardBuffer::kCopyPaste,
/* data_dst = */ nullptr)) {
LOG(ERROR) << "HTML still in clipboard.";
return false;
}
- if (!clipboard->IsFormatAvailable(ClipboardFormatType::GetPlainTextType(),
+ if (!clipboard->IsFormatAvailable(ClipboardFormatType::PlainTextType(),
ClipboardBuffer::kCopyPaste,
/* data_dst = */ nullptr)) {
LOG(ERROR) << "Plain text not in clipboard.";
diff --git a/chromium/ui/base/clipboard/clipboard_data.cc b/chromium/ui/base/clipboard/clipboard_data.cc
index 0bc1e93ec74..f78d9f67b91 100644
--- a/chromium/ui/base/clipboard/clipboard_data.cc
+++ b/chromium/ui/base/clipboard/clipboard_data.cc
@@ -58,6 +58,31 @@ bool ClipboardData::operator!=(const ClipboardData& that) const {
return !(*this == that);
}
+absl::optional<size_t> ClipboardData::size() const {
+ if (format_ & static_cast<int>(ClipboardInternalFormat::kFilenames))
+ return absl::nullopt;
+ size_t total_size = 0;
+ if (format_ & static_cast<int>(ClipboardInternalFormat::kText))
+ total_size += text_.size();
+ if (format_ & static_cast<int>(ClipboardInternalFormat::kHtml)) {
+ total_size += markup_data_.size();
+ total_size += url_.size();
+ }
+ if (format_ & static_cast<int>(ClipboardInternalFormat::kSvg))
+ total_size += svg_data_.size();
+ if (format_ & static_cast<int>(ClipboardInternalFormat::kRtf))
+ total_size += rtf_data_.size();
+ if (format_ & static_cast<int>(ClipboardInternalFormat::kBookmark)) {
+ total_size += bookmark_title_.size();
+ total_size += bookmark_url_.size();
+ }
+ if (format_ & static_cast<int>(ClipboardInternalFormat::kPng))
+ total_size += png_.size();
+ if (format_ & static_cast<int>(ClipboardInternalFormat::kCustom))
+ total_size += custom_data_data_.size();
+ return total_size;
+}
+
void ClipboardData::SetPngData(std::vector<uint8_t> png) {
png_ = std::move(png);
format_ |= static_cast<int>(ClipboardInternalFormat::kPng);
diff --git a/chromium/ui/base/clipboard/clipboard_data.h b/chromium/ui/base/clipboard/clipboard_data.h
index 3f4a550655a..3bf22dbe16a 100644
--- a/chromium/ui/base/clipboard/clipboard_data.h
+++ b/chromium/ui/base/clipboard/clipboard_data.h
@@ -9,6 +9,7 @@
#include <vector>
#include "base/component_export.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/clipboard/file_info.h"
#include "ui/base/data_transfer_policy/data_transfer_endpoint.h"
@@ -46,6 +47,10 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ClipboardData {
// Bitmask of ClipboardInternalFormat types.
int format() const { return format_; }
+ // Returns the total size of the data in clipboard, or absl::nullopt if it
+ // can't be determined.
+ absl::optional<size_t> size() const;
+
const std::string& text() const { return text_; }
void set_text(const std::string& text) {
text_ = text;
diff --git a/chromium/ui/base/clipboard/clipboard_format_type.h b/chromium/ui/base/clipboard/clipboard_format_type.h
index 03451964918..e3ca57b66ea 100644
--- a/chromium/ui/base/clipboard/clipboard_format_type.h
+++ b/chromium/ui/base/clipboard/clipboard_format_type.h
@@ -14,7 +14,7 @@
#include "build/build_config.h"
#if defined(OS_WIN)
-#include <objidl.h>
+#include "base/win/windows_types.h"
#endif
#if defined(OS_APPLE)
@@ -45,48 +45,57 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES) ClipboardFormatType {
std::string Serialize() const;
static ClipboardFormatType Deserialize(const std::string& serialization);
- // Gets the ClipboardFormatType corresponding to an arbitrary format string,
- // registering it with the system if needed. Due to Windows/Linux
- // limitations, please place limits on the amount of GetType calls with unique
- // |format_string| arguments, when ingesting |format_string| from
- // untrusted sources, such as renderer processes. In Windows, a failure will
- // return an invalid format with Deserialize()'ed value of "0".
+ // Gets the ClipboardFormatType corresponding to the standard formats.
static ClipboardFormatType GetType(const std::string& format_string);
// Get format identifiers for various types.
- static const ClipboardFormatType& GetFilenamesType();
- static const ClipboardFormatType& GetUrlType();
- static const ClipboardFormatType& GetPlainTextType();
- static const ClipboardFormatType& GetWebKitSmartPasteType();
+ static const ClipboardFormatType& FilenamesType();
+ static const ClipboardFormatType& UrlType();
+ static const ClipboardFormatType& PlainTextType();
+ static const ClipboardFormatType& WebKitSmartPasteType();
// Win: MS HTML Format, Other: Generic HTML format
- static const ClipboardFormatType& GetHtmlType();
- static const ClipboardFormatType& GetSvgType();
- static const ClipboardFormatType& GetRtfType();
- static const ClipboardFormatType& GetPngType();
+ static const ClipboardFormatType& HtmlType();
+ static const ClipboardFormatType& SvgType();
+ static const ClipboardFormatType& RtfType();
+ static const ClipboardFormatType& PngType();
// TODO(crbug.com/1201018): Remove this type.
- static const ClipboardFormatType& GetBitmapType();
- static const ClipboardFormatType& GetWebCustomDataType();
+ static const ClipboardFormatType& BitmapType();
+ static const ClipboardFormatType& WebCustomDataType();
#if defined(OS_WIN)
// ANSI formats. Only Windows differentiates between ANSI and UNICODE formats
// in ClipboardFormatType. Reference:
// https://docs.microsoft.com/en-us/windows/win32/learnwin32/working-with-strings
- static const ClipboardFormatType& GetUrlAType();
- static const ClipboardFormatType& GetPlainTextAType();
- static const ClipboardFormatType& GetFilenameAType();
+ static const ClipboardFormatType& UrlAType();
+ static const ClipboardFormatType& PlainTextAType();
+ static const ClipboardFormatType& FilenameAType();
// Firefox text/html
- static const ClipboardFormatType& GetTextHtmlType();
- static const ClipboardFormatType& GetCFHDropType();
- static const ClipboardFormatType& GetFileDescriptorAType();
- static const ClipboardFormatType& GetFileDescriptorType();
- static const ClipboardFormatType& GetFileContentZeroType();
- static const ClipboardFormatType& GetFileContentAtIndexType(LONG index);
- static const ClipboardFormatType& GetFilenameType();
- static const ClipboardFormatType& GetIDListType();
- static const ClipboardFormatType& GetMozUrlType();
+ static const ClipboardFormatType& TextHtmlType();
+ static const ClipboardFormatType& CFHDropType();
+ static const ClipboardFormatType& FileDescriptorAType();
+ static const ClipboardFormatType& FileDescriptorType();
+ static const ClipboardFormatType& FileContentZeroType();
+ static const ClipboardFormatType& FileContentAtIndexType(LONG index);
+ static const ClipboardFormatType& FilenameType();
+ static const ClipboardFormatType& IDListType();
+ static const ClipboardFormatType& MozUrlType();
#endif
+ // For custom formats we hardcode the web custom format prefix and the index.
+ // Due to Windows/Linux limitations, please place limits on the amount of
+ // `WebCustomFormatName` calls with unique `index` argument.
+ static std::string WebCustomFormatName(int index);
+ // Gets the ClipboardFormatType corresponding to a format string,
+ // registering it with the system if needed.
+ static ClipboardFormatType CustomPlatformType(
+ const std::string& format_string);
+ // Returns the web custom format map that has the mapping of MIME types to
+ // custom format names.
+ static const ClipboardFormatType& WebCustomFormatMap();
+ // Returns the web custom format map name.
+ static std::string WebCustomFormatMapName();
+
// ClipboardFormatType can be used in a set on some platforms.
bool operator<(const ClipboardFormatType& other) const;
@@ -94,7 +103,7 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES) ClipboardFormatType {
// if the format isn't found.
std::string GetName() const;
#if defined(OS_WIN)
- const FORMATETC& ToFormatEtc() const { return data_; }
+ const FORMATETC& ToFormatEtc() const { return *ChromeToWindowsType(&data_); }
#elif defined(OS_APPLE)
NSString* ToNSString() const { return data_; }
// Custom copy and assignment constructor to handle NSString.
@@ -126,11 +135,11 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES) ClipboardFormatType {
// an index into the data (the first file corresponds to index 0). This
// function returns a map of index to CFSTR_FILECONTENTS clipboard format
// type.
- static std::map<LONG, ClipboardFormatType>& GetFileContentTypeMap();
+ static std::map<LONG, ClipboardFormatType>& FileContentTypeMap();
// FORMATETC:
// https://docs.microsoft.com/en-us/windows/desktop/com/the-formatetc-structure
- FORMATETC data_;
+ CHROME_FORMATETC data_;
#elif defined(USE_AURA) || defined(OS_ANDROID) || defined(OS_FUCHSIA)
explicit ClipboardFormatType(const std::string& native_format);
std::string data_;
diff --git a/chromium/ui/base/clipboard/clipboard_format_type_android.cc b/chromium/ui/base/clipboard/clipboard_format_type_android.cc
index ded6f0c1d1a..7af255bc24c 100644
--- a/chromium/ui/base/clipboard/clipboard_format_type_android.cc
+++ b/chromium/ui/base/clipboard/clipboard_format_type_android.cc
@@ -4,6 +4,9 @@
#include "ui/base/clipboard/clipboard_format_type.h"
+#include "base/strings/strcat.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
#include "ui/base/clipboard/clipboard_constants.h"
namespace ui {
@@ -38,6 +41,31 @@ bool ClipboardFormatType::operator==(const ClipboardFormatType& other) const {
return data_ == other.data_;
}
+// static
+std::string ClipboardFormatType::WebCustomFormatName(int index) {
+ return base::StrCat({"application/web;type=\"custom/format",
+ base::NumberToString(index), "\""});
+}
+
+// static
+std::string ClipboardFormatType::WebCustomFormatMapName() {
+ return "application/web;type=\"custom/formatmap\"";
+}
+
+// static
+ClipboardFormatType ClipboardFormatType::CustomPlatformType(
+ const std::string& format_string) {
+ DCHECK(base::IsStringASCII(format_string));
+ return ClipboardFormatType::Deserialize(format_string);
+}
+
+// static
+const ClipboardFormatType& ClipboardFormatType::WebCustomFormatMap() {
+ static base::NoDestructor<ClipboardFormatType> type(
+ ClipboardFormatType::WebCustomFormatMapName());
+ return *type;
+}
+
// Various predefined ClipboardFormatTypes.
// static
@@ -47,61 +75,62 @@ ClipboardFormatType ClipboardFormatType::GetType(
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetFilenamesType() {
+const ClipboardFormatType& ClipboardFormatType::FilenamesType() {
static base::NoDestructor<ClipboardFormatType> type(kMimeTypeURIList);
return *type;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetUrlType() {
+const ClipboardFormatType& ClipboardFormatType::UrlType() {
static base::NoDestructor<ClipboardFormatType> type(kMimeTypeMozillaURL);
return *type;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetPlainTextType() {
+const ClipboardFormatType& ClipboardFormatType::PlainTextType() {
static base::NoDestructor<ClipboardFormatType> type(kMimeTypeText);
return *type;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetWebKitSmartPasteType() {
+const ClipboardFormatType& ClipboardFormatType::WebKitSmartPasteType() {
static base::NoDestructor<ClipboardFormatType> type(
kMimeTypeWebkitSmartPaste);
return *type;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetHtmlType() {
+const ClipboardFormatType& ClipboardFormatType::HtmlType() {
static base::NoDestructor<ClipboardFormatType> type(kMimeTypeHTML);
return *type;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetSvgType() {
+const ClipboardFormatType& ClipboardFormatType::SvgType() {
static base::NoDestructor<ClipboardFormatType> type(kMimeTypeSvg);
return *type;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetRtfType() {
+const ClipboardFormatType& ClipboardFormatType::RtfType() {
static base::NoDestructor<ClipboardFormatType> type(kMimeTypeRTF);
return *type;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetPngType() {
+const ClipboardFormatType& ClipboardFormatType::PngType() {
static base::NoDestructor<ClipboardFormatType> type(kMimeTypePNG);
return *type;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetBitmapType() {
- return ClipboardFormatType::GetPngType();
+const ClipboardFormatType& ClipboardFormatType::BitmapType() {
+ static base::NoDestructor<ClipboardFormatType> type(kMimeTypeImageURI);
+ return *type;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetWebCustomDataType() {
+const ClipboardFormatType& ClipboardFormatType::WebCustomDataType() {
static base::NoDestructor<ClipboardFormatType> type(kMimeTypeWebCustomData);
return *type;
}
diff --git a/chromium/ui/base/clipboard/clipboard_format_type_aura.cc b/chromium/ui/base/clipboard/clipboard_format_type_aura.cc
index a47fd9ae246..078fa98592f 100644
--- a/chromium/ui/base/clipboard/clipboard_format_type_aura.cc
+++ b/chromium/ui/base/clipboard/clipboard_format_type_aura.cc
@@ -4,14 +4,17 @@
#include "ui/base/clipboard/clipboard_format_type.h"
+#include "base/strings/strcat.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
#include "ui/base/clipboard/clipboard_constants.h"
namespace ui {
-// TODO(huangdarwin): Investigate creating a new clipboard_format_type_x11 as a
-// wrapper around an X11 ::Atom. This wasn't possible in the past, because unit
-// tests spawned a new X11 server for each test, meaning Atom numeric values
-// didn't persist across tests.
+// TODO(crbug.com/1123230): Investigate creating a new clipboard_format_type_x11
+// as a wrapper around an X11 ::Atom. This wasn't possible in the past, because
+// unit tests spawned a new X11 server for each test, meaning Atom numeric
+// values didn't persist across tests.
ClipboardFormatType::ClipboardFormatType() = default;
ClipboardFormatType::~ClipboardFormatType() = default;
@@ -41,6 +44,31 @@ bool ClipboardFormatType::operator==(const ClipboardFormatType& other) const {
return data_ == other.data_;
}
+// static
+ClipboardFormatType ClipboardFormatType::CustomPlatformType(
+ const std::string& format_string) {
+ DCHECK(base::IsStringASCII(format_string));
+ return ClipboardFormatType::Deserialize(format_string);
+}
+
+// static
+std::string ClipboardFormatType::WebCustomFormatName(int index) {
+ return base::StrCat({"application/web;type=\"custom/format",
+ base::NumberToString(index), "\""});
+}
+
+// static
+std::string ClipboardFormatType::WebCustomFormatMapName() {
+ return "application/web;type=\"custom/formatmap\"";
+}
+
+// static
+const ClipboardFormatType& ClipboardFormatType::WebCustomFormatMap() {
+ static base::NoDestructor<ClipboardFormatType> type(
+ ClipboardFormatType::WebCustomFormatMapName());
+ return *type;
+}
+
// Various predefined ClipboardFormatTypes.
// static
@@ -50,61 +78,61 @@ ClipboardFormatType ClipboardFormatType::GetType(
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetFilenamesType() {
+const ClipboardFormatType& ClipboardFormatType::FilenamesType() {
static base::NoDestructor<ClipboardFormatType> type(kMimeTypeURIList);
return *type;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetUrlType() {
+const ClipboardFormatType& ClipboardFormatType::UrlType() {
static base::NoDestructor<ClipboardFormatType> type(kMimeTypeMozillaURL);
return *type;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetPlainTextType() {
+const ClipboardFormatType& ClipboardFormatType::PlainTextType() {
static base::NoDestructor<ClipboardFormatType> type(kMimeTypeText);
return *type;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetHtmlType() {
+const ClipboardFormatType& ClipboardFormatType::HtmlType() {
static base::NoDestructor<ClipboardFormatType> type(kMimeTypeHTML);
return *type;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetSvgType() {
+const ClipboardFormatType& ClipboardFormatType::SvgType() {
static base::NoDestructor<ClipboardFormatType> type(kMimeTypeSvg);
return *type;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetRtfType() {
+const ClipboardFormatType& ClipboardFormatType::RtfType() {
static base::NoDestructor<ClipboardFormatType> type(kMimeTypeRTF);
return *type;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetPngType() {
+const ClipboardFormatType& ClipboardFormatType::PngType() {
static base::NoDestructor<ClipboardFormatType> type(kMimeTypePNG);
return *type;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetBitmapType() {
- return ClipboardFormatType::GetPngType();
+const ClipboardFormatType& ClipboardFormatType::BitmapType() {
+ return ClipboardFormatType::PngType();
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetWebKitSmartPasteType() {
+const ClipboardFormatType& ClipboardFormatType::WebKitSmartPasteType() {
static base::NoDestructor<ClipboardFormatType> type(
kMimeTypeWebkitSmartPaste);
return *type;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetWebCustomDataType() {
+const ClipboardFormatType& ClipboardFormatType::WebCustomDataType() {
static base::NoDestructor<ClipboardFormatType> type(kMimeTypeWebCustomData);
return *type;
}
diff --git a/chromium/ui/base/clipboard/clipboard_format_type_mac.mm b/chromium/ui/base/clipboard/clipboard_format_type_mac.mm
index 719582aa1da..f370fc8745e 100644
--- a/chromium/ui/base/clipboard/clipboard_format_type_mac.mm
+++ b/chromium/ui/base/clipboard/clipboard_format_type_mac.mm
@@ -6,12 +6,17 @@
#import <Cocoa/Cocoa.h>
+#include "base/strings/strcat.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
#include "base/strings/sys_string_conversions.h"
#include "ui/base/clipboard/clipboard_constants.h"
namespace ui {
// ClipboardFormatType implementation.
+// MacOS formats are implemented via Uniform Type Identifiers, documented here:
+// https://developer.apple.com/library/archive/documentation/General/Conceptual/DevPedia-CocoaCore/UniformTypeIdentifier.html#//apple_ref/doc/uid/TP40008195-CH60
ClipboardFormatType::ClipboardFormatType() : data_(nil) {}
ClipboardFormatType::ClipboardFormatType(NSString* native_format)
@@ -55,6 +60,30 @@ bool ClipboardFormatType::operator<(const ClipboardFormatType& other) const {
return [data_ compare:other.data_] == NSOrderedAscending;
}
+// static
+std::string ClipboardFormatType::WebCustomFormatName(int index) {
+ return base::StrCat({"com.web.custom.format", base::NumberToString(index)});
+}
+
+// static
+std::string ClipboardFormatType::WebCustomFormatMapName() {
+ return "com.web.custom.format.map";
+}
+
+// static
+const ClipboardFormatType& ClipboardFormatType::WebCustomFormatMap() {
+ static base::NoDestructor<ClipboardFormatType> type(
+ base::SysUTF8ToNSString(ClipboardFormatType::WebCustomFormatMapName()));
+ return *type;
+}
+
+// static
+ClipboardFormatType ClipboardFormatType::CustomPlatformType(
+ const std::string& format_string) {
+ DCHECK(base::IsStringASCII(format_string));
+ return ClipboardFormatType::Deserialize(format_string);
+}
+
// Various predefined ClipboardFormatTypes.
// static
@@ -64,60 +93,60 @@ ClipboardFormatType ClipboardFormatType::GetType(
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetFilenamesType() {
+const ClipboardFormatType& ClipboardFormatType::FilenamesType() {
static base::NoDestructor<ClipboardFormatType> type(NSFilenamesPboardType);
return *type;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetUrlType() {
+const ClipboardFormatType& ClipboardFormatType::UrlType() {
static base::NoDestructor<ClipboardFormatType> type(NSURLPboardType);
return *type;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetPlainTextType() {
+const ClipboardFormatType& ClipboardFormatType::PlainTextType() {
static base::NoDestructor<ClipboardFormatType> type(NSPasteboardTypeString);
return *type;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetHtmlType() {
+const ClipboardFormatType& ClipboardFormatType::HtmlType() {
static base::NoDestructor<ClipboardFormatType> type(NSHTMLPboardType);
return *type;
}
-const ClipboardFormatType& ClipboardFormatType::GetSvgType() {
+const ClipboardFormatType& ClipboardFormatType::SvgType() {
static base::NoDestructor<ClipboardFormatType> type(kImageSvg);
return *type;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetRtfType() {
+const ClipboardFormatType& ClipboardFormatType::RtfType() {
static base::NoDestructor<ClipboardFormatType> type(NSRTFPboardType);
return *type;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetPngType() {
+const ClipboardFormatType& ClipboardFormatType::PngType() {
static base::NoDestructor<ClipboardFormatType> type(NSPasteboardTypePNG);
return *type;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetBitmapType() {
+const ClipboardFormatType& ClipboardFormatType::BitmapType() {
static base::NoDestructor<ClipboardFormatType> type(NSTIFFPboardType);
return *type;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetWebKitSmartPasteType() {
+const ClipboardFormatType& ClipboardFormatType::WebKitSmartPasteType() {
static base::NoDestructor<ClipboardFormatType> type(kWebSmartPastePboardType);
return *type;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetWebCustomDataType() {
+const ClipboardFormatType& ClipboardFormatType::WebCustomDataType() {
static base::NoDestructor<ClipboardFormatType> type(kWebCustomDataPboardType);
return *type;
}
diff --git a/chromium/ui/base/clipboard/clipboard_format_type_win.cc b/chromium/ui/base/clipboard/clipboard_format_type_win.cc
index 8834346f7ae..b700f40eba7 100644
--- a/chromium/ui/base/clipboard/clipboard_format_type_win.cc
+++ b/chromium/ui/base/clipboard/clipboard_format_type_win.cc
@@ -9,74 +9,19 @@
#include "base/containers/flat_map.h"
#include "base/memory/ptr_util.h"
-#include "base/metrics/histogram_functions.h"
#include "base/no_destructor.h"
#include "base/notreached.h"
+#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
-
-namespace {
-
-const base::flat_map<UINT, std::string>& PredefinedFormatToNameMap() {
- // These formats are described in winuser.h and
- // https://docs.microsoft.com/en-us/windows/win32/dataxchg/standard-clipboard-formats
- static const base::NoDestructor<base::flat_map<UINT, std::string>>
- format_to_name({
- {CF_TEXT, "CF_TEXT"},
- {CF_DIF, "CF_DIF"},
- {CF_TIFF, "CF_TIFF"},
- {CF_OEMTEXT, "CF_OEMTEXT"},
- {CF_DIB, "CF_DIB"},
- {CF_PENDATA, "CF_PENDATA"},
- {CF_RIFF, "CF_RIFF"},
- {CF_WAVE, "CF_WAVE"},
- {CF_UNICODETEXT, "CF_UNICODETEXT"},
- {CF_DIBV5, "CF_DIBV5"},
- {CF_OWNERDISPLAY, "CF_OWNERDISPLAY"},
-
- // These formats are predefined but explicitly blocked from use,
- // either due to passing along handles, or concerns regarding exposing
- // private information.
- // {CF_MAX, "CF_MAX"},
- // {CF_PRIVATEFIRST, "CF_PRIVATEFIRST"},
- // {CF_PRIVATELAST, "CF_PRIVATELAST"},
- // {CF_GDIOBJFIRST, "CF_GDIOBJFIRST"},
- // {CF_GDIOBJLAST, "CF_GDIOBJLAST"},
- // {CF_BITMAP, "CF_BITMAP"},
- // {CF_SYLK, "CF_SYLK"},
- // {CF_METAFILEPICT, "CF_METAFILEPICT"},
- // {CF_DSPTEXT, "CF_DSPTEXT"},
- // {CF_DSPBITMAP, "CF_DSPBITMAP"},
- // {CF_DSPMETAFILEPICT, "CF_DSPMETAFILEPICT"},
- // {CF_DSPENHMETAFILE, "CF_DSPENHMETAFILE"},
- // {CF_ENHMETAFILE, "CF_ENHMETAFILE"},
- // {CF_HDROP, "CF_HDROP"},
- // {CF_LOCALE, "CF_LOCALE"},
- // {CF_PALETTE, "CF_PALETTE"},
-
- });
- return *format_to_name;
-}
-
-const base::flat_map<std::string, UINT>& PredefinedNameToFormatMap() {
- // Use lambda constructor for thread-safe initialization of name_to_format.
- static const base::NoDestructor<base::flat_map<std::string, UINT>>
- name_to_format([] {
- base::flat_map<std::string, UINT> new_name_to_format;
- const auto& format_to_name = PredefinedFormatToNameMap();
- new_name_to_format.reserve(format_to_name.size());
- for (const auto& it : format_to_name)
- new_name_to_format.emplace(it.second, it.first);
- return new_name_to_format;
- }());
- return *name_to_format;
-}
-
-} // namespace
+#include "ui/base/clipboard/clipboard_constants.h"
namespace ui {
// ClipboardFormatType implementation.
+// Windows formats are backed by "Clipboard Formats", documented here:
+// https://docs.microsoft.com/en-us/windows/win32/dataxchg/clipboard-formats
ClipboardFormatType::ClipboardFormatType() = default;
ClipboardFormatType::ClipboardFormatType(UINT native_format)
@@ -91,17 +36,7 @@ ClipboardFormatType::ClipboardFormatType(UINT native_format,
DWORD tymed)
: data_{/* .cfFormat */ static_cast<CLIPFORMAT>(native_format),
/* .ptd */ nullptr, /* .dwAspect */ DVASPECT_CONTENT,
- /* .lindex */ index, /* .tymed*/ tymed} {
- // Log the frequency of invalid formats being input into the constructor.
- if (!native_format) {
- static int error_count = 0;
- ++error_count;
- // TODO(https://crbug.com/1000919): Evaluate and remove UMA metrics after
- // enough data is gathered.
- base::UmaHistogramCounts100("Clipboard.RegisterClipboardFormatFailure",
- error_count);
- }
-}
+ /* .lindex */ index, /* .tymed*/ tymed} {}
ClipboardFormatType::~ClipboardFormatType() = default;
@@ -122,22 +57,59 @@ ClipboardFormatType ClipboardFormatType::Deserialize(
return ClipboardFormatType(clipboard_format);
}
+// static
+std::string ClipboardFormatType::WebCustomFormatName(int index) {
+ return base::StrCat({"Web Custom Format", base::NumberToString(index)});
+}
+
+// static
+std::string ClipboardFormatType::WebCustomFormatMapName() {
+ return "Web Custom Format Map";
+}
+
+// static
+ClipboardFormatType ClipboardFormatType::CustomPlatformType(
+ const std::string& format_string) {
+ // Once these formats are registered, `RegisterClipboardFormat` just returns
+ // the `cfFormat` associated with it and doesn't register a new format.
+ DCHECK(base::IsStringASCII(format_string));
+ return ClipboardFormatType(
+ ::RegisterClipboardFormat(base::ASCIIToWide(format_string).c_str()));
+}
+
+// static
+const ClipboardFormatType& ClipboardFormatType::WebCustomFormatMap() {
+ static base::NoDestructor<ClipboardFormatType> format(
+ ::RegisterClipboardFormat(
+ base::ASCIIToWide(ClipboardFormatType::WebCustomFormatMapName())
+ .c_str()));
+ return *format;
+}
+
std::string ClipboardFormatType::GetName() const {
- const auto& predefined_format_to_name = PredefinedFormatToNameMap();
- const auto it = predefined_format_to_name.find(data_.cfFormat);
- if (it != predefined_format_to_name.end())
- return it->second;
-
- constexpr size_t kMaxFormatSize = 1024;
- static base::NoDestructor<std::vector<wchar_t>> name_buffer(kMaxFormatSize);
- int name_size = GetClipboardFormatName(data_.cfFormat, name_buffer->data(),
- kMaxFormatSize);
- if (!name_size) {
- // Input format doesn't exist or is predefined.
- return std::string();
+ if (ClipboardFormatType::PlainTextAType().ToFormatEtc().cfFormat ==
+ data_.cfFormat) {
+ return kMimeTypeText;
}
-
- return base::WideToUTF8(std::wstring(name_buffer->data(), name_size));
+ if (ClipboardFormatType::HtmlType().ToFormatEtc().cfFormat ==
+ data_.cfFormat) {
+ return kMimeTypeHTML;
+ }
+ if (ClipboardFormatType::RtfType().ToFormatEtc().cfFormat == data_.cfFormat) {
+ return kMimeTypeRTF;
+ }
+ if (CF_DIB == data_.cfFormat)
+ return kMimeTypePNG;
+ if (ClipboardFormatType::CFHDropType().ToFormatEtc().cfFormat ==
+ data_.cfFormat ||
+ ClipboardFormatType::FilenameType().ToFormatEtc().cfFormat ==
+ data_.cfFormat ||
+ ClipboardFormatType::FilenameAType().ToFormatEtc().cfFormat ==
+ data_.cfFormat) {
+ return kMimeTypeURIList;
+ }
+ // Not a standard format type.
+ return std::string();
}
bool ClipboardFormatType::operator<(const ClipboardFormatType& other) const {
@@ -153,11 +125,6 @@ bool ClipboardFormatType::operator==(const ClipboardFormatType& other) const {
// static
ClipboardFormatType ClipboardFormatType::GetType(
const std::string& format_string) {
- const auto& predefined_name_to_format = PredefinedNameToFormatMap();
- const auto it = predefined_name_to_format.find(format_string);
- if (it != predefined_name_to_format.end())
- return ClipboardFormatType(it->second);
-
return ClipboardFormatType(
::RegisterClipboardFormat(base::ASCIIToWide(format_string).c_str()));
}
@@ -169,19 +136,19 @@ ClipboardFormatType ClipboardFormatType::GetType(
// ClipboardFormatTypes thread-safe on all platforms.
// static
-const ClipboardFormatType& ClipboardFormatType::GetFilenamesType() {
- return GetFilenameType();
+const ClipboardFormatType& ClipboardFormatType::FilenamesType() {
+ return FilenameType();
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetUrlType() {
+const ClipboardFormatType& ClipboardFormatType::UrlType() {
static base::NoDestructor<ClipboardFormatType> format(
::RegisterClipboardFormat(CFSTR_INETURLW));
return *format;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetPlainTextType() {
+const ClipboardFormatType& ClipboardFormatType::PlainTextType() {
static base::NoDestructor<ClipboardFormatType> format(CF_UNICODETEXT);
return *format;
}
@@ -189,14 +156,14 @@ const ClipboardFormatType& ClipboardFormatType::GetPlainTextType() {
// MS HTML Format
// static
-const ClipboardFormatType& ClipboardFormatType::GetHtmlType() {
+const ClipboardFormatType& ClipboardFormatType::HtmlType() {
static base::NoDestructor<ClipboardFormatType> format(
::RegisterClipboardFormat(L"HTML Format"));
return *format;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetSvgType() {
+const ClipboardFormatType& ClipboardFormatType::SvgType() {
static base::NoDestructor<ClipboardFormatType> format(
::RegisterClipboardFormat(CFSTR_MIME_SVG_XML));
return *format;
@@ -205,40 +172,40 @@ const ClipboardFormatType& ClipboardFormatType::GetSvgType() {
// MS RTF Format
// static
-const ClipboardFormatType& ClipboardFormatType::GetRtfType() {
+const ClipboardFormatType& ClipboardFormatType::RtfType() {
static base::NoDestructor<ClipboardFormatType> format(
::RegisterClipboardFormat(L"Rich Text Format"));
return *format;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetPngType() {
+const ClipboardFormatType& ClipboardFormatType::PngType() {
static base::NoDestructor<ClipboardFormatType> format(
::RegisterClipboardFormat(L"PNG"));
return *format;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetBitmapType() {
+const ClipboardFormatType& ClipboardFormatType::BitmapType() {
static base::NoDestructor<ClipboardFormatType> format(CF_DIBV5);
return *format;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetUrlAType() {
+const ClipboardFormatType& ClipboardFormatType::UrlAType() {
static base::NoDestructor<ClipboardFormatType> format(
::RegisterClipboardFormat(CFSTR_INETURLA));
return *format;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetPlainTextAType() {
+const ClipboardFormatType& ClipboardFormatType::PlainTextAType() {
static base::NoDestructor<ClipboardFormatType> format(CF_TEXT);
return *format;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetFilenameAType() {
+const ClipboardFormatType& ClipboardFormatType::FilenameAType() {
static base::NoDestructor<ClipboardFormatType> format(
::RegisterClipboardFormat(CFSTR_FILENAMEA));
return *format;
@@ -246,14 +213,14 @@ const ClipboardFormatType& ClipboardFormatType::GetFilenameAType() {
// Firefox text/html
// static
-const ClipboardFormatType& ClipboardFormatType::GetTextHtmlType() {
+const ClipboardFormatType& ClipboardFormatType::TextHtmlType() {
static base::NoDestructor<ClipboardFormatType> format(
::RegisterClipboardFormat(L"text/html"));
return *format;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetCFHDropType() {
+const ClipboardFormatType& ClipboardFormatType::CFHDropType() {
static base::NoDestructor<ClipboardFormatType> format(CF_HDROP);
return *format;
}
@@ -262,24 +229,24 @@ const ClipboardFormatType& ClipboardFormatType::GetCFHDropType() {
// ANSI format (e.g., it could be that it doesn't support Unicode). So need to
// register both the ANSI and Unicode file group descriptors.
// static
-const ClipboardFormatType& ClipboardFormatType::GetFileDescriptorAType() {
+const ClipboardFormatType& ClipboardFormatType::FileDescriptorAType() {
static base::NoDestructor<ClipboardFormatType> format(
::RegisterClipboardFormat(CFSTR_FILEDESCRIPTORA));
return *format;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetFileDescriptorType() {
+const ClipboardFormatType& ClipboardFormatType::FileDescriptorType() {
static base::NoDestructor<ClipboardFormatType> format(
::RegisterClipboardFormat(CFSTR_FILEDESCRIPTORW));
return *format;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetFileContentZeroType() {
+const ClipboardFormatType& ClipboardFormatType::FileContentZeroType() {
// This uses a storage media type of TYMED_HGLOBAL, which is not commonly
// used with CFSTR_FILECONTENTS (but used in Chromium--see
- // OSExchangeDataProviderWin::SetFileContents). Use GetFileContentAtIndexType
+ // OSExchangeDataProviderWin::SetFileContents). Use FileContentAtIndexType
// if TYMED_ISTREAM and TYMED_ISTORAGE are needed.
// TODO(https://crbug.com/950756): Should TYMED_ISTREAM / TYMED_ISTORAGE be
// used instead of TYMED_HGLOBAL in
@@ -292,17 +259,16 @@ const ClipboardFormatType& ClipboardFormatType::GetFileContentZeroType() {
}
// static
-std::map<LONG, ClipboardFormatType>&
-ClipboardFormatType::GetFileContentTypeMap() {
+std::map<LONG, ClipboardFormatType>& ClipboardFormatType::FileContentTypeMap() {
static base::NoDestructor<std::map<LONG, ClipboardFormatType>>
index_to_type_map;
return *index_to_type_map;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetFileContentAtIndexType(
+const ClipboardFormatType& ClipboardFormatType::FileContentAtIndexType(
LONG index) {
- auto& index_to_type_map = GetFileContentTypeMap();
+ auto& index_to_type_map = FileContentTypeMap();
auto insert_or_assign_result = index_to_type_map.insert(
{index,
@@ -312,35 +278,35 @@ const ClipboardFormatType& ClipboardFormatType::GetFileContentAtIndexType(
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetFilenameType() {
+const ClipboardFormatType& ClipboardFormatType::FilenameType() {
static base::NoDestructor<ClipboardFormatType> format(
::RegisterClipboardFormat(CFSTR_FILENAMEW));
return *format;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetIDListType() {
+const ClipboardFormatType& ClipboardFormatType::IDListType() {
static base::NoDestructor<ClipboardFormatType> format(
::RegisterClipboardFormat(CFSTR_SHELLIDLIST));
return *format;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetMozUrlType() {
+const ClipboardFormatType& ClipboardFormatType::MozUrlType() {
static base::NoDestructor<ClipboardFormatType> format(
::RegisterClipboardFormat(L"text/x-moz-url"));
return *format;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetWebKitSmartPasteType() {
+const ClipboardFormatType& ClipboardFormatType::WebKitSmartPasteType() {
static base::NoDestructor<ClipboardFormatType> format(
::RegisterClipboardFormat(L"WebKit Smart Paste Format"));
return *format;
}
// static
-const ClipboardFormatType& ClipboardFormatType::GetWebCustomDataType() {
+const ClipboardFormatType& ClipboardFormatType::WebCustomDataType() {
// TODO(http://crbug.com/106449): Standardize this name.
static base::NoDestructor<ClipboardFormatType> format(
::RegisterClipboardFormat(L"Chromium Web Custom MIME Data Format"));
diff --git a/chromium/ui/base/clipboard/clipboard_mac.h b/chromium/ui/base/clipboard/clipboard_mac.h
index f45d165368a..45d9d4b4e11 100644
--- a/chromium/ui/base/clipboard/clipboard_mac.h
+++ b/chromium/ui/base/clipboard/clipboard_mac.h
@@ -10,19 +10,31 @@
#include "base/component_export.h"
#include "base/gtest_prod_util.h"
-#include "base/macros.h"
+#include "base/mac/foundation_util.h"
#include "ui/base/clipboard/clipboard.h"
@class NSPasteboard;
namespace ui {
+// Documentation on the underlying MacOS API this ultimately abstracts is
+// available at https://developer.apple.com/documentation/appkit/nspasteboard
+// and
+// https://developer.apple.com/library/archive/documentation/General/Conceptual/Devpedia-CocoaApp/Pasteboard.html.
class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ClipboardMac : public Clipboard {
+ public:
+ ClipboardMac(const ClipboardMac&) = delete;
+ ClipboardMac& operator=(const ClipboardMac&) = delete;
+
private:
- FRIEND_TEST_ALL_PREFIXES(ClipboardMacTest, ReadImageRetina);
- FRIEND_TEST_ALL_PREFIXES(ClipboardMacTest, ReadImageNonRetina);
- FRIEND_TEST_ALL_PREFIXES(ClipboardMacTest, EmptyImage);
- FRIEND_TEST_ALL_PREFIXES(ClipboardMacTest, PDFImage);
+ FRIEND_TEST_ALL_PREFIXES(ClipboardMacTest, ReadImageRetina_Bitmap);
+ FRIEND_TEST_ALL_PREFIXES(ClipboardMacTest, ReadImageNonRetina_Bitmap);
+ FRIEND_TEST_ALL_PREFIXES(ClipboardMacTest, EmptyImage_Bitmap);
+ FRIEND_TEST_ALL_PREFIXES(ClipboardMacTest, PDFImage_Bitmap);
+ FRIEND_TEST_ALL_PREFIXES(ClipboardMacTest, ReadImageRetina_Png);
+ FRIEND_TEST_ALL_PREFIXES(ClipboardMacTest, ReadImageNonRetina_Png);
+ FRIEND_TEST_ALL_PREFIXES(ClipboardMacTest, EmptyImage_Png);
+ FRIEND_TEST_ALL_PREFIXES(ClipboardMacTest, PDFImage_Png);
friend class Clipboard;
ClipboardMac();
@@ -31,7 +43,8 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ClipboardMac : public Clipboard {
// Clipboard overrides:
void OnPreShutdown() override;
DataTransferEndpoint* GetSource(ClipboardBuffer buffer) const override;
- uint64_t GetSequenceNumber(ClipboardBuffer buffer) const override;
+ const ClipboardSequenceNumberToken& GetSequenceNumber(
+ ClipboardBuffer buffer) const override;
bool IsFormatAvailable(const ClipboardFormatType& format,
ClipboardBuffer buffer,
const DataTransferEndpoint* data_dst) const override;
@@ -81,12 +94,9 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ClipboardMac : public Clipboard {
void ReadData(const ClipboardFormatType& format,
const DataTransferEndpoint* data_dst,
std::string* result) const override;
- void WritePortableRepresentations(
+ void WritePortableAndPlatformRepresentations(
ClipboardBuffer buffer,
const ObjectMap& objects,
- std::unique_ptr<DataTransferEndpoint> data_src) override;
- void WritePlatformRepresentations(
- ClipboardBuffer buffer,
std::vector<Clipboard::PlatformRepresentation> platform_representations,
std::unique_ptr<DataTransferEndpoint> data_src) override;
void WriteText(const char* text_data, size_t text_len) override;
@@ -107,10 +117,16 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ClipboardMac : public Clipboard {
const char* data_data,
size_t data_len) override;
+ std::vector<uint8_t> ReadPngInternal(ClipboardBuffer buffer,
+ NSPasteboard* pasteboard) const;
SkBitmap ReadImageInternal(ClipboardBuffer buffer,
NSPasteboard* pasteboard) const;
- DISALLOW_COPY_AND_ASSIGN(ClipboardMac);
+ // Mapping of OS-provided sequence number to a unique token.
+ mutable struct {
+ NSInteger sequence_number;
+ ClipboardSequenceNumberToken token;
+ } clipboard_sequence_;
};
} // namespace ui
diff --git a/chromium/ui/base/clipboard/clipboard_mac.mm b/chromium/ui/base/clipboard/clipboard_mac.mm
index 76b08ef78e5..0419eb5beb8 100644
--- a/chromium/ui/base/clipboard/clipboard_mac.mm
+++ b/chromium/ui/base/clipboard/clipboard_mac.mm
@@ -6,19 +6,19 @@
#import <Cocoa/Cocoa.h>
#include <stdint.h>
+#include "ui/base/clipboard/clipboard.h"
#include <limits>
-#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/mac/foundation_util.h"
#include "base/mac/mac_util.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/mac/scoped_nsobject.h"
+#include "base/memory/ref_counted_memory.h"
#include "base/no_destructor.h"
#include "base/notreached.h"
-#include "base/stl_util.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/sys_string_conversions.h"
@@ -29,13 +29,15 @@
#import "third_party/mozilla/NSPasteboard+Utils.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/clipboard/clipboard_constants.h"
+#include "ui/base/clipboard/clipboard_format_type.h"
#include "ui/base/clipboard/clipboard_metrics.h"
#include "ui/base/clipboard/clipboard_util_mac.h"
#include "ui/base/clipboard/custom_data_helper.h"
#include "ui/base/data_transfer_policy/data_transfer_endpoint.h"
-#include "ui/base/ui_base_features.h"
#include "ui/gfx/canvas.h"
+#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/image/image.h"
#include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
#include "url/gurl.h"
@@ -50,6 +52,23 @@ NSPasteboard* GetPasteboard() {
return pasteboard;
}
+base::scoped_nsobject<NSImage> GetNSImage(NSPasteboard* pasteboard) {
+ // If the pasteboard's image data is not to its liking, the guts of NSImage
+ // may throw, and that exception will leak. Prevent a crash in that case;
+ // a blank image is better.
+ base::scoped_nsobject<NSImage> image;
+ @try {
+ if (pasteboard)
+ image.reset([[NSImage alloc] initWithPasteboard:pasteboard]);
+ } @catch (id exception) {
+ }
+ if (!image)
+ return base::scoped_nsobject<NSImage>();
+ if ([[image representations] count] == 0u)
+ return base::scoped_nsobject<NSImage>();
+ return image;
+}
+
} // namespace
// Clipboard factory method.
@@ -76,11 +95,17 @@ DataTransferEndpoint* ClipboardMac::GetSource(ClipboardBuffer buffer) const {
return nullptr;
}
-uint64_t ClipboardMac::GetSequenceNumber(ClipboardBuffer buffer) const {
+const ClipboardSequenceNumberToken& ClipboardMac::GetSequenceNumber(
+ ClipboardBuffer buffer) const {
DCHECK(CalledOnValidThread());
DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
- return [GetPasteboard() changeCount];
+ NSInteger sequence_number = [GetPasteboard() changeCount];
+ if (sequence_number != clipboard_sequence_.sequence_number) {
+ // Generate a unique token associated with the current sequence number.
+ clipboard_sequence_ = {sequence_number, ClipboardSequenceNumberToken()};
+ }
+ return clipboard_sequence_.token;
}
// |data_dst| is not used. It's only passed to be consistent with other
@@ -92,21 +117,21 @@ bool ClipboardMac::IsFormatAvailable(
DCHECK(CalledOnValidThread());
DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
- // Only support filenames if chrome://flags#clipboard-filenames is enabled.
- if (format == ClipboardFormatType::GetFilenamesType() &&
- !base::FeatureList::IsEnabled(features::kClipboardFilenames)) {
- return false;
- }
-
// https://crbug.com/1016740#c21
base::scoped_nsobject<NSArray> types([[GetPasteboard() types] retain]);
// Safari only places RTF on the pasteboard, never HTML. We can convert RTF
// to HTML, so the presence of either indicates success when looking for HTML.
- if ([format.ToNSString() isEqualToString:NSHTMLPboardType]) {
+ if (format == ClipboardFormatType::HtmlType()) {
return [types containsObject:NSHTMLPboardType] ||
[types containsObject:NSRTFPboardType];
}
+ // Chrome can retrieve an image from the clipboard as either a bitmap or PNG.
+ if (format == ClipboardFormatType::PngType() ||
+ format == ClipboardFormatType::BitmapType()) {
+ return [types containsObject:NSPasteboardTypePNG] ||
+ [types containsObject:NSTIFFPboardType];
+ }
return [types containsObject:format.ToNSString()];
}
@@ -146,16 +171,15 @@ void ClipboardMac::ReadAvailableTypes(
NSPasteboard* pb = GetPasteboard();
types->clear();
- if (IsFormatAvailable(ClipboardFormatType::GetPlainTextType(), buffer,
- data_dst))
+ if (IsFormatAvailable(ClipboardFormatType::PlainTextType(), buffer, data_dst))
types->push_back(base::UTF8ToUTF16(kMimeTypeText));
- if (IsFormatAvailable(ClipboardFormatType::GetHtmlType(), buffer, data_dst))
+ if (IsFormatAvailable(ClipboardFormatType::HtmlType(), buffer, data_dst))
types->push_back(base::UTF8ToUTF16(kMimeTypeHTML));
- if (IsFormatAvailable(ClipboardFormatType::GetSvgType(), buffer, data_dst))
+ if (IsFormatAvailable(ClipboardFormatType::SvgType(), buffer, data_dst))
types->push_back(base::UTF8ToUTF16(kMimeTypeSvg));
- if (IsFormatAvailable(ClipboardFormatType::GetRtfType(), buffer, data_dst))
+ if (IsFormatAvailable(ClipboardFormatType::RtfType(), buffer, data_dst))
types->push_back(base::UTF8ToUTF16(kMimeTypeRTF));
- if (IsFormatAvailable(ClipboardFormatType::GetFilenamesType(), buffer,
+ if (IsFormatAvailable(ClipboardFormatType::FilenamesType(), buffer,
data_dst)) {
types->push_back(base::UTF8ToUTF16(kMimeTypeURIList));
} else if (pb && [NSImage canInitWithPasteboard:pb]) {
@@ -275,7 +299,7 @@ void ClipboardMac::ReadRTF(ClipboardBuffer buffer,
DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
RecordRead(ClipboardFormatMetric::kRtf);
- return ReadData(ClipboardFormatType::GetRtfType(), data_dst, result);
+ return ReadData(ClipboardFormatType::RtfType(), data_dst, result);
}
// |data_dst| is not used. It's only passed to be consistent with other
@@ -283,8 +307,8 @@ void ClipboardMac::ReadRTF(ClipboardBuffer buffer,
void ClipboardMac::ReadPng(ClipboardBuffer buffer,
const DataTransferEndpoint* data_dst,
ReadPngCallback callback) const {
- // TODO(crbug.com/1201018): Implement this.
- NOTIMPLEMENTED();
+ RecordRead(ClipboardFormatMetric::kPng);
+ std::move(callback).Run(ReadPngInternal(buffer, GetPasteboard()));
}
// |data_dst| is not used. It's only passed to be consistent with other
@@ -367,23 +391,9 @@ void ClipboardMac::ReadData(const ClipboardFormatType& format,
// |data_src| is not used. It's only passed to be consistent with other
// platforms.
-void ClipboardMac::WritePortableRepresentations(
+void ClipboardMac::WritePortableAndPlatformRepresentations(
ClipboardBuffer buffer,
const ObjectMap& objects,
- std::unique_ptr<DataTransferEndpoint> data_src) {
- DCHECK(CalledOnValidThread());
- DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
-
- [GetPasteboard() declareTypes:@[] owner:nil];
-
- for (const auto& object : objects)
- DispatchPortableRepresentation(object.first, object.second);
-}
-
-// |data_src| is not used. It's only passed to be consistent with other
-// platforms.
-void ClipboardMac::WritePlatformRepresentations(
- ClipboardBuffer buffer,
std::vector<Clipboard::PlatformRepresentation> platform_representations,
std::unique_ptr<DataTransferEndpoint> data_src) {
DCHECK(CalledOnValidThread());
@@ -392,6 +402,8 @@ void ClipboardMac::WritePlatformRepresentations(
[GetPasteboard() declareTypes:@[] owner:nil];
DispatchPlatformRepresentations(std::move(platform_representations));
+ for (const auto& object : objects)
+ DispatchPortableRepresentation(object.first, object.second);
}
void ClipboardMac::WriteText(const char* text_data, size_t text_len) {
@@ -420,7 +432,7 @@ void ClipboardMac::WriteSvg(const char* markup_data, size_t markup_len) {
}
void ClipboardMac::WriteRTF(const char* rtf_data, size_t data_len) {
- WriteData(ClipboardFormatType::GetRtfType(), rtf_data, data_len);
+ WriteData(ClipboardFormatType::RtfType(), rtf_data, data_len);
}
void ClipboardMac::WriteFilenames(std::vector<ui::FileInfo> filenames) {
@@ -458,15 +470,7 @@ void ClipboardMac::WriteBitmap(const SkBitmap& bitmap) {
NOTREACHED() << "SkBitmapToNSImageWithColorSpace failed";
return;
}
- // TODO (https://crbug.com/971916): Write NSImage directly to clipboard.
- // An API to ask the NSImage to write itself to the clipboard comes in 10.6 :(
- // For now, spit out the image as a TIFF.
- NSData* tiff_data = [image TIFFRepresentation];
- LOG_IF(ERROR, tiff_data == nullptr)
- << "Failed to allocate image for clipboard";
- if (tiff_data) {
- [GetPasteboard() setData:tiff_data forType:NSTIFFPboardType];
- }
+ [GetPasteboard() writeObjects:@[ image ]];
}
void ClipboardMac::WriteData(const ClipboardFormatType& format,
@@ -479,43 +483,33 @@ void ClipboardMac::WriteData(const ClipboardFormatType& format,
// Write an extra flavor that signifies WebKit was the last to modify the
// pasteboard. This flavor has no data.
void ClipboardMac::WriteWebSmartPaste() {
- NSString* format =
- ClipboardFormatType::GetWebKitSmartPasteType().ToNSString();
+ NSString* format = ClipboardFormatType::WebKitSmartPasteType().ToNSString();
[GetPasteboard() setData:nil forType:format];
}
+std::vector<uint8_t> ClipboardMac::ReadPngInternal(
+ ClipboardBuffer buffer,
+ NSPasteboard* pasteboard) const {
+ DCHECK(CalledOnValidThread());
+ DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
+
+ base::scoped_nsobject<NSImage> image = GetNSImage(pasteboard);
+ if (!image)
+ return std::vector<uint8_t>();
+
+ scoped_refptr<base::RefCountedMemory> mem = gfx::Image(image).As1xPNGBytes();
+ std::vector<uint8_t> image_data(mem->data(), mem->data() + mem->size());
+ return image_data;
+}
+
SkBitmap ClipboardMac::ReadImageInternal(ClipboardBuffer buffer,
NSPasteboard* pasteboard) const {
DCHECK(CalledOnValidThread());
DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
- // If the pasteboard's image data is not to its liking, the guts of NSImage
- // may throw, and that exception will leak. Prevent a crash in that case;
- // a blank image is better.
- base::scoped_nsobject<NSImage> image;
- @try {
- // TODO(crbug.com/1175483): remove first branch of this code when
- // ClipboardFilenames feature flag is removed.
- if ([[pasteboard types] containsObject:NSFilenamesPboardType]) {
- // -[NSImage initWithPasteboard:] gets confused with copies of a single
- // file from the Finder, so extract the path ourselves.
- // http://crbug.com/553686
- NSArray* paths = [pasteboard propertyListForType:NSFilenamesPboardType];
- if ([paths count]) {
- // If N number of files are selected from finder, choose the last one.
- image.reset([[NSImage alloc]
- initWithContentsOfURL:[NSURL fileURLWithPath:[paths lastObject]]]);
- }
- } else {
- if (pasteboard)
- image.reset([[NSImage alloc] initWithPasteboard:pasteboard]);
- }
- } @catch (id exception) {
- }
+ base::scoped_nsobject<NSImage> image = GetNSImage(pasteboard);
if (!image)
return SkBitmap();
- if ([[image representations] count] == 0u)
- return SkBitmap();
// This logic prevents loss of pixels from retina images, where size != pixel
// size. In an ideal world, the concept of "retina-ness" would be plumbed all
diff --git a/chromium/ui/base/clipboard/clipboard_mac_unittest.mm b/chromium/ui/base/clipboard/clipboard_mac_unittest.mm
index 7e84fa95d1d..4b4886495d9 100644
--- a/chromium/ui/base/clipboard/clipboard_mac_unittest.mm
+++ b/chromium/ui/base/clipboard/clipboard_mac_unittest.mm
@@ -4,6 +4,8 @@
#import "ui/base/clipboard/clipboard_mac.h"
+#include <vector>
+
#import <AppKit/AppKit.h>
#include "base/mac/scoped_cftyperef.h"
@@ -14,6 +16,7 @@
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/clipboard/clipboard_buffer.h"
#include "ui/base/clipboard/clipboard_util_mac.h"
+#include "ui/gfx/codec/png_codec.h"
@interface RedView : NSView
@end
@@ -69,7 +72,7 @@ class ClipboardMacTest : public PlatformTest {
}
};
-TEST_F(ClipboardMacTest, ReadImageRetina) {
+TEST_F(ClipboardMacTest, ReadImageRetina_Bitmap) {
int32_t width = 99;
int32_t height = 101;
scoped_refptr<UniquePasteboard> pasteboard = new UniquePasteboard;
@@ -85,7 +88,25 @@ TEST_F(ClipboardMacTest, ReadImageRetina) {
EXPECT_EQ(2 * height, bitmap.height());
}
-TEST_F(ClipboardMacTest, ReadImageNonRetina) {
+TEST_F(ClipboardMacTest, ReadImageRetina_Png) {
+ int32_t width = 99;
+ int32_t height = 101;
+ scoped_refptr<UniquePasteboard> pasteboard = new UniquePasteboard;
+ base::scoped_nsobject<NSImage> image = CreateImage(width, height, true);
+ [pasteboard->get() writeObjects:@[ image.get() ]];
+
+ Clipboard* clipboard = Clipboard::GetForCurrentThread();
+ ClipboardMac* clipboard_mac = static_cast<ClipboardMac*>(clipboard);
+
+ std::vector<uint8_t> png_data = clipboard_mac->ReadPngInternal(
+ ClipboardBuffer::kCopyPaste, pasteboard->get());
+ SkBitmap bitmap;
+ gfx::PNGCodec::Decode(png_data.data(), png_data.size(), &bitmap);
+ EXPECT_EQ(2 * width, bitmap.width());
+ EXPECT_EQ(2 * height, bitmap.height());
+}
+
+TEST_F(ClipboardMacTest, ReadImageNonRetina_Bitmap) {
int32_t width = 99;
int32_t height = 101;
scoped_refptr<UniquePasteboard> pasteboard = new UniquePasteboard;
@@ -101,7 +122,25 @@ TEST_F(ClipboardMacTest, ReadImageNonRetina) {
EXPECT_EQ(height, bitmap.height());
}
-TEST_F(ClipboardMacTest, EmptyImage) {
+TEST_F(ClipboardMacTest, ReadImageNonRetina_Png) {
+ int32_t width = 99;
+ int32_t height = 101;
+ scoped_refptr<UniquePasteboard> pasteboard = new UniquePasteboard;
+ base::scoped_nsobject<NSImage> image = CreateImage(width, height, false);
+ [pasteboard->get() writeObjects:@[ image.get() ]];
+
+ Clipboard* clipboard = Clipboard::GetForCurrentThread();
+ ClipboardMac* clipboard_mac = static_cast<ClipboardMac*>(clipboard);
+
+ std::vector<uint8_t> png_data = clipboard_mac->ReadPngInternal(
+ ClipboardBuffer::kCopyPaste, pasteboard->get());
+ SkBitmap bitmap;
+ gfx::PNGCodec::Decode(png_data.data(), png_data.size(), &bitmap);
+ EXPECT_EQ(width, bitmap.width());
+ EXPECT_EQ(height, bitmap.height());
+}
+
+TEST_F(ClipboardMacTest, EmptyImage_Bitmap) {
base::scoped_nsobject<NSImage> image([[NSImage alloc] init]);
scoped_refptr<UniquePasteboard> pasteboard = new UniquePasteboard;
[pasteboard->get() writeObjects:@[ image.get() ]];
@@ -115,7 +154,23 @@ TEST_F(ClipboardMacTest, EmptyImage) {
EXPECT_EQ(0, bitmap.height());
}
-TEST_F(ClipboardMacTest, PDFImage) {
+TEST_F(ClipboardMacTest, EmptyImage_Png) {
+ base::scoped_nsobject<NSImage> image([[NSImage alloc] init]);
+ scoped_refptr<UniquePasteboard> pasteboard = new UniquePasteboard;
+ [pasteboard->get() writeObjects:@[ image.get() ]];
+
+ Clipboard* clipboard = Clipboard::GetForCurrentThread();
+ ClipboardMac* clipboard_mac = static_cast<ClipboardMac*>(clipboard);
+
+ std::vector<uint8_t> png_data = clipboard_mac->ReadPngInternal(
+ ClipboardBuffer::kCopyPaste, pasteboard->get());
+ SkBitmap bitmap;
+ gfx::PNGCodec::Decode(png_data.data(), png_data.size(), &bitmap);
+ EXPECT_EQ(0, bitmap.width());
+ EXPECT_EQ(0, bitmap.height());
+}
+
+TEST_F(ClipboardMacTest, PDFImage_Bitmap) {
int32_t width = 99;
int32_t height = 101;
NSRect frame = NSMakeRect(0, 0, width, height);
@@ -138,4 +193,29 @@ TEST_F(ClipboardMacTest, PDFImage) {
EXPECT_EQ(height, bitmap.height());
}
+TEST_F(ClipboardMacTest, PDFImage_Png) {
+ int32_t width = 99;
+ int32_t height = 101;
+ NSRect frame = NSMakeRect(0, 0, width, height);
+
+ // This seems like a round-about way of getting a NSPDFImageRep to shove into
+ // an NSPasteboard. However, I haven't found any other way of generating a
+ // "PDF" image that makes NSPasteboard happy.
+ base::scoped_nsobject<NSView> v([[RedView alloc] initWithFrame:frame]);
+ NSData* data = [v dataWithPDFInsideRect:frame];
+
+ scoped_refptr<UniquePasteboard> pasteboard = new UniquePasteboard;
+ [pasteboard->get() setData:data forType:NSPasteboardTypePDF];
+
+ Clipboard* clipboard = Clipboard::GetForCurrentThread();
+ ClipboardMac* clipboard_mac = static_cast<ClipboardMac*>(clipboard);
+
+ std::vector<uint8_t> png_data = clipboard_mac->ReadPngInternal(
+ ClipboardBuffer::kCopyPaste, pasteboard->get());
+ SkBitmap bitmap;
+ gfx::PNGCodec::Decode(png_data.data(), png_data.size(), &bitmap);
+ EXPECT_EQ(width, bitmap.width());
+ EXPECT_EQ(height, bitmap.height());
+}
+
} // namespace ui
diff --git a/chromium/ui/base/clipboard/clipboard_monitor.h b/chromium/ui/base/clipboard/clipboard_monitor.h
index 5ba97a41eaf..5a7ad27ea28 100644
--- a/chromium/ui/base/clipboard/clipboard_monitor.h
+++ b/chromium/ui/base/clipboard/clipboard_monitor.h
@@ -6,7 +6,6 @@
#define UI_BASE_CLIPBOARD_CLIPBOARD_MONITOR_H_
#include "base/component_export.h"
-#include "base/macros.h"
#include "base/no_destructor.h"
#include "base/observer_list.h"
#include "base/threading/thread_checker.h"
@@ -23,6 +22,9 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ClipboardMonitor {
public:
static ClipboardMonitor* GetInstance();
+ ClipboardMonitor(const ClipboardMonitor&) = delete;
+ ClipboardMonitor& operator=(const ClipboardMonitor&) = delete;
+
// Adds an observer.
void AddObserver(ClipboardObserver* observer);
@@ -46,8 +48,6 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ClipboardMonitor {
base::ObserverList<ClipboardObserver>::Unchecked observers_;
THREAD_CHECKER(thread_checker_);
-
- DISALLOW_COPY_AND_ASSIGN(ClipboardMonitor);
};
} // namespace ui
diff --git a/chromium/ui/base/clipboard/clipboard_non_backed.cc b/chromium/ui/base/clipboard/clipboard_non_backed.cc
index 3cacd71de81..89bdb1068bb 100644
--- a/chromium/ui/base/clipboard/clipboard_non_backed.cc
+++ b/chromium/ui/base/clipboard/clipboard_non_backed.cc
@@ -13,9 +13,8 @@
#include <utility>
#include "base/check_op.h"
-#include "base/feature_list.h"
+#include "base/containers/contains.h"
#include "base/files/file_path.h"
-#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/no_destructor.h"
#include "base/notreached.h"
@@ -32,7 +31,6 @@
#include "ui/base/clipboard/custom_data_helper.h"
#include "ui/base/data_transfer_policy/data_transfer_endpoint.h"
#include "ui/base/data_transfer_policy/data_transfer_policy_controller.h"
-#include "ui/base/ui_base_features.h"
#include "ui/gfx/geometry/size.h"
namespace ui {
@@ -88,16 +86,19 @@ bool IsRegisteredInstance(const Clipboard* clipboard) {
class ClipboardInternal {
public:
ClipboardInternal() = default;
-
+ ClipboardInternal(const ClipboardInternal&) = delete;
+ ClipboardInternal& operator=(const ClipboardInternal&) = delete;
~ClipboardInternal() = default;
void Clear() {
- ++sequence_number_;
+ sequence_number_ = ClipboardSequenceNumberToken();
data_.reset();
ClipboardMonitor::GetInstance()->NotifyClipboardDataChanged();
}
- uint64_t sequence_number() const { return sequence_number_; }
+ const ClipboardSequenceNumberToken& sequence_number() const {
+ return sequence_number_;
+ }
// Returns the current clipboard data, which may be nullptr if nothing has
// been written since the last Clear().
@@ -180,6 +181,14 @@ class ClipboardInternal {
*result = data->rtf_data();
}
+ // Reads png from the ClipboardData.
+ std::vector<uint8_t> ReadPng() const {
+ if (!HasFormat(ClipboardInternalFormat::kPng))
+ return std::vector<uint8_t>();
+
+ return GetData()->png();
+ }
+
// Reads image from the ClipboardData.
SkBitmap ReadImage() const {
SkBitmap img;
@@ -243,7 +252,7 @@ class ClipboardInternal {
DCHECK(data);
std::unique_ptr<ClipboardData> previous_data = std::move(data_);
data_ = std::move(data);
- ++sequence_number_;
+ sequence_number_ = ClipboardSequenceNumberToken();
ClipboardMonitor::GetInstance()->NotifyClipboardDataChanged();
return previous_data;
}
@@ -254,7 +263,8 @@ class ClipboardInternal {
auto* data = GetData();
if (!policy_controller || !data)
return true;
- return policy_controller->IsClipboardReadAllowed(data->source(), data_dst);
+ return policy_controller->IsClipboardReadAllowed(data->source(), data_dst,
+ data->size());
}
private:
@@ -268,9 +278,7 @@ class ClipboardInternal {
std::unique_ptr<ClipboardData> data_;
// Sequence number uniquely identifying clipboard state.
- uint64_t sequence_number_ = 0;
-
- DISALLOW_COPY_AND_ASSIGN(ClipboardInternal);
+ ClipboardSequenceNumberToken sequence_number_;
};
// Helper class to build a ClipboardData object and write it to clipboard.
@@ -407,7 +415,8 @@ DataTransferEndpoint* ClipboardNonBacked::GetSource(
return data ? data->source() : nullptr;
}
-uint64_t ClipboardNonBacked::GetSequenceNumber(ClipboardBuffer buffer) const {
+const ClipboardSequenceNumberToken& ClipboardNonBacked::GetSequenceNumber(
+ ClipboardBuffer buffer) const {
DCHECK(CalledOnValidThread());
return clipboard_internal_->sequence_number();
}
@@ -422,29 +431,27 @@ bool ClipboardNonBacked::IsFormatAvailable(
if (!clipboard_internal_->IsReadAllowed(data_dst))
return false;
- if (format == ClipboardFormatType::GetPlainTextType() ||
- format == ClipboardFormatType::GetUrlType())
+ if (format == ClipboardFormatType::PlainTextType() ||
+ format == ClipboardFormatType::UrlType())
return clipboard_internal_->IsFormatAvailable(
ClipboardInternalFormat::kText);
- if (format == ClipboardFormatType::GetHtmlType())
+ if (format == ClipboardFormatType::HtmlType())
return clipboard_internal_->IsFormatAvailable(
ClipboardInternalFormat::kHtml);
- if (format == ClipboardFormatType::GetSvgType())
+ if (format == ClipboardFormatType::SvgType())
return clipboard_internal_->IsFormatAvailable(
ClipboardInternalFormat::kSvg);
- if (format == ClipboardFormatType::GetRtfType())
+ if (format == ClipboardFormatType::RtfType())
return clipboard_internal_->IsFormatAvailable(
ClipboardInternalFormat::kRtf);
- if (format == ClipboardFormatType::GetPngType() ||
- format == ClipboardFormatType::GetBitmapType())
+ if (format == ClipboardFormatType::PngType() ||
+ format == ClipboardFormatType::BitmapType())
return clipboard_internal_->IsFormatAvailable(
ClipboardInternalFormat::kPng);
- if (format == ClipboardFormatType::GetWebKitSmartPasteType())
+ if (format == ClipboardFormatType::WebKitSmartPasteType())
return clipboard_internal_->IsFormatAvailable(
ClipboardInternalFormat::kWeb);
- // Only support filenames if chrome://flags#clipboard-filenames is enabled.
- if (format == ClipboardFormatType::GetFilenamesType() &&
- base::FeatureList::IsEnabled(features::kClipboardFilenames))
+ if (format == ClipboardFormatType::FilenamesType())
return clipboard_internal_->IsFormatAvailable(
ClipboardInternalFormat::kFilenames);
const ClipboardData* data = clipboard_internal_->GetData();
@@ -468,20 +475,18 @@ void ClipboardNonBacked::ReadAvailableTypes(
return;
types->clear();
- if (IsFormatAvailable(ClipboardFormatType::GetPlainTextType(), buffer,
- data_dst))
+ if (IsFormatAvailable(ClipboardFormatType::PlainTextType(), buffer, data_dst))
types->push_back(
- base::UTF8ToUTF16(ClipboardFormatType::GetPlainTextType().GetName()));
- if (IsFormatAvailable(ClipboardFormatType::GetHtmlType(), buffer, data_dst))
+ base::UTF8ToUTF16(ClipboardFormatType::PlainTextType().GetName()));
+ if (IsFormatAvailable(ClipboardFormatType::HtmlType(), buffer, data_dst))
types->push_back(
- base::UTF8ToUTF16(ClipboardFormatType::GetHtmlType().GetName()));
- if (IsFormatAvailable(ClipboardFormatType::GetRtfType(), buffer, data_dst))
+ base::UTF8ToUTF16(ClipboardFormatType::HtmlType().GetName()));
+ if (IsFormatAvailable(ClipboardFormatType::RtfType(), buffer, data_dst))
types->push_back(
- base::UTF8ToUTF16(ClipboardFormatType::GetRtfType().GetName()));
- if (IsFormatAvailable(ClipboardFormatType::GetBitmapType(), buffer, data_dst))
+ base::UTF8ToUTF16(ClipboardFormatType::RtfType().GetName()));
+ if (IsFormatAvailable(ClipboardFormatType::BitmapType(), buffer, data_dst))
types->push_back(base::UTF8ToUTF16(kMimeTypePNG));
- if (IsFormatAvailable(ClipboardFormatType::GetFilenamesType(), buffer,
- data_dst))
+ if (IsFormatAvailable(ClipboardFormatType::FilenamesType(), buffer, data_dst))
types->push_back(base::UTF8ToUTF16(kMimeTypeURIList));
if (clipboard_internal_->IsFormatAvailable(
@@ -505,21 +510,20 @@ ClipboardNonBacked::ReadAvailablePlatformSpecificFormatNames(
return types;
// Includes all non-pickled AvailableTypes.
- if (IsFormatAvailable(ClipboardFormatType::GetPlainTextType(), buffer,
+ if (IsFormatAvailable(ClipboardFormatType::PlainTextType(), buffer,
data_dst)) {
types.push_back(
- base::UTF8ToUTF16(ClipboardFormatType::GetPlainTextType().GetName()));
+ base::UTF8ToUTF16(ClipboardFormatType::PlainTextType().GetName()));
}
- if (IsFormatAvailable(ClipboardFormatType::GetHtmlType(), buffer, data_dst)) {
+ if (IsFormatAvailable(ClipboardFormatType::HtmlType(), buffer, data_dst)) {
types.push_back(
- base::UTF8ToUTF16(ClipboardFormatType::GetHtmlType().GetName()));
+ base::UTF8ToUTF16(ClipboardFormatType::HtmlType().GetName()));
}
- if (IsFormatAvailable(ClipboardFormatType::GetRtfType(), buffer, data_dst)) {
+ if (IsFormatAvailable(ClipboardFormatType::RtfType(), buffer, data_dst)) {
types.push_back(
- base::UTF8ToUTF16(ClipboardFormatType::GetRtfType().GetName()));
+ base::UTF8ToUTF16(ClipboardFormatType::RtfType().GetName()));
}
- if (IsFormatAvailable(ClipboardFormatType::GetBitmapType(), buffer,
- data_dst)) {
+ if (IsFormatAvailable(ClipboardFormatType::BitmapType(), buffer, data_dst)) {
types.push_back(base::UTF8ToUTF16(kMimeTypePNG));
}
@@ -609,8 +613,18 @@ void ClipboardNonBacked::ReadPng(ClipboardBuffer buffer,
const DataTransferEndpoint* data_dst,
ReadPngCallback callback) const {
DCHECK(CalledOnValidThread());
- // TODO(crbug.com/1201018): Implement this.
- NOTIMPLEMENTED();
+
+ if (!clipboard_internal_->IsReadAllowed(data_dst)) {
+ std::move(callback).Run(std::vector<uint8_t>());
+ return;
+ }
+
+ RecordRead(ClipboardFormatMetric::kPng);
+ std::move(callback).Run(clipboard_internal_->ReadPng());
+
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+ ClipboardMonitor::GetInstance()->NotifyClipboardDataRead();
+#endif
}
void ClipboardNonBacked::ReadImage(ClipboardBuffer buffer,
@@ -707,26 +721,17 @@ bool ClipboardNonBacked::IsSelectionBufferAvailable() const {
}
#endif // defined(USE_OZONE)
-void ClipboardNonBacked::WritePortableRepresentations(
+void ClipboardNonBacked::WritePortableAndPlatformRepresentations(
ClipboardBuffer buffer,
const ObjectMap& objects,
- std::unique_ptr<DataTransferEndpoint> data_src) {
- DCHECK(CalledOnValidThread());
- DCHECK(IsSupportedClipboardBuffer(buffer));
- for (const auto& object : objects)
- DispatchPortableRepresentation(object.first, object.second);
- ClipboardDataBuilder::CommitToClipboard(clipboard_internal_.get(),
- std::move(data_src));
-}
-
-void ClipboardNonBacked::WritePlatformRepresentations(
- ClipboardBuffer buffer,
std::vector<Clipboard::PlatformRepresentation> platform_representations,
std::unique_ptr<DataTransferEndpoint> data_src) {
DCHECK(CalledOnValidThread());
DCHECK(IsSupportedClipboardBuffer(buffer));
DispatchPlatformRepresentations(std::move(platform_representations));
+ for (const auto& object : objects)
+ DispatchPortableRepresentation(object.first, object.second);
ClipboardDataBuilder::CommitToClipboard(clipboard_internal_.get(),
std::move(data_src));
diff --git a/chromium/ui/base/clipboard/clipboard_non_backed.h b/chromium/ui/base/clipboard/clipboard_non_backed.h
index 17403e75391..7b67ca07b02 100644
--- a/chromium/ui/base/clipboard/clipboard_non_backed.h
+++ b/chromium/ui/base/clipboard/clipboard_non_backed.h
@@ -10,7 +10,6 @@
#include "base/component_export.h"
#include "base/gtest_prod_util.h"
-#include "base/macros.h"
#include "ui/base/clipboard/clipboard.h"
namespace ui {
@@ -32,6 +31,9 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ClipboardNonBacked
// the current thread is in fact an instance of ClipboardNonBacked.
static ClipboardNonBacked* GetForCurrentThread();
+ ClipboardNonBacked(const ClipboardNonBacked&) = delete;
+ ClipboardNonBacked& operator=(const ClipboardNonBacked&) = delete;
+
// Returns the current ClipboardData.
const ClipboardData* GetClipboardData(DataTransferEndpoint* data_dst) const;
@@ -42,7 +44,8 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ClipboardNonBacked
// Clipboard overrides:
DataTransferEndpoint* GetSource(ClipboardBuffer buffer) const override;
- uint64_t GetSequenceNumber(ClipboardBuffer buffer) const override;
+ const ClipboardSequenceNumberToken& GetSequenceNumber(
+ ClipboardBuffer buffer) const override;
private:
friend class Clipboard;
@@ -103,12 +106,9 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ClipboardNonBacked
#if defined(USE_OZONE)
bool IsSelectionBufferAvailable() const override;
#endif // defined(USE_OZONE)
- void WritePortableRepresentations(
+ void WritePortableAndPlatformRepresentations(
ClipboardBuffer buffer,
const ObjectMap& objects,
- std::unique_ptr<DataTransferEndpoint> data_src) override;
- void WritePlatformRepresentations(
- ClipboardBuffer buffer,
std::vector<Clipboard::PlatformRepresentation> platform_representations,
std::unique_ptr<DataTransferEndpoint> data_src) override;
void WriteText(const char* text_data, size_t text_len) override;
@@ -130,8 +130,6 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ClipboardNonBacked
size_t data_len) override;
const std::unique_ptr<ClipboardInternal> clipboard_internal_;
-
- DISALLOW_COPY_AND_ASSIGN(ClipboardNonBacked);
};
} // namespace ui
diff --git a/chromium/ui/base/clipboard/clipboard_non_backed_unittest.cc b/chromium/ui/base/clipboard/clipboard_non_backed_unittest.cc
index 963dbc4297f..9cba3aa94d3 100644
--- a/chromium/ui/base/clipboard/clipboard_non_backed_unittest.cc
+++ b/chromium/ui/base/clipboard/clipboard_non_backed_unittest.cc
@@ -8,12 +8,12 @@
#include <string>
#include <vector>
+#include "base/pickle.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_feature_list.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/clipboard/clipboard_data.h"
-#include "ui/base/ui_base_features.h"
+#include "ui/base/clipboard/custom_data_helper.h"
namespace ui {
namespace {
@@ -92,9 +92,7 @@ TEST_F(ClipboardNonBackedTest, AdminWriteDoesNotRecordHistograms) {
// Tests that site bookmark URLs are accessed as text, and
// IsFormatAvailable('text/uri-list') is only true for files.
TEST_F(ClipboardNonBackedTest, TextURIList) {
- base::test::ScopedFeatureList features;
- features.InitWithFeatures({features::kClipboardFilenames}, {});
- EXPECT_EQ("text/uri-list", ClipboardFormatType::GetFilenamesType().GetName());
+ EXPECT_EQ("text/uri-list", ClipboardFormatType::FilenamesType().GetName());
auto data = std::make_unique<ClipboardData>();
data->set_bookmark_url("http://example.com");
@@ -103,27 +101,47 @@ TEST_F(ClipboardNonBackedTest, TextURIList) {
clipboard()->ReadAvailableTypes(ClipboardBuffer::kCopyPaste,
/*data_dst=*/nullptr, &types);
- // With bookmark data, available types should be only 'text/plain'.
+ // Bookmark data uses mime type 'text/plain'.
EXPECT_EQ(std::vector<std::string>({"text/plain"}), UTF8Types(types));
- EXPECT_TRUE(clipboard()->IsFormatAvailable(ClipboardFormatType::GetUrlType(),
+ EXPECT_TRUE(clipboard()->IsFormatAvailable(ClipboardFormatType::UrlType(),
ClipboardBuffer::kCopyPaste,
/*data_dst=*/nullptr));
EXPECT_FALSE(clipboard()->IsFormatAvailable(
- ClipboardFormatType::GetFilenamesType(), ClipboardBuffer::kCopyPaste,
+ ClipboardFormatType::FilenamesType(), ClipboardBuffer::kCopyPaste,
/*data_dst=*/nullptr));
- // With filenames data, available types should be 'text/uri-list'.
+ // Filenames data uses mime type 'text/uri-list'.
data = std::make_unique<ClipboardData>();
data->set_filenames({FileInfo(base::FilePath("/path"), base::FilePath())});
clipboard()->WriteClipboardData(std::move(data));
clipboard()->ReadAvailableTypes(ClipboardBuffer::kCopyPaste,
/*data_dst=*/nullptr, &types);
EXPECT_EQ(std::vector<std::string>({"text/uri-list"}), UTF8Types(types));
- EXPECT_FALSE(clipboard()->IsFormatAvailable(ClipboardFormatType::GetUrlType(),
+ EXPECT_FALSE(clipboard()->IsFormatAvailable(ClipboardFormatType::UrlType(),
ClipboardBuffer::kCopyPaste,
/*data_dst=*/nullptr));
EXPECT_TRUE(clipboard()->IsFormatAvailable(
- ClipboardFormatType::GetFilenamesType(), ClipboardBuffer::kCopyPaste,
+ ClipboardFormatType::FilenamesType(), ClipboardBuffer::kCopyPaste,
+ /*data_dst=*/nullptr));
+
+ // Filenames data uses mime type 'text/uri-list', but clients can also set
+ // 'text/uri-list' as one of the custom data types. When it is set as a custom
+ // type, it will be returned from ReadAvailableTypes(), but
+ // IsFormatAvailable(FilenamesType()) is false.
+ data = std::make_unique<ClipboardData>();
+ base::flat_map<std::u16string, std::u16string> custom_data;
+ custom_data[u"text/uri-list"] = u"data";
+ base::Pickle pickle;
+ ui::WriteCustomDataToPickle(custom_data, &pickle);
+ data->SetCustomData(
+ ui::ClipboardFormatType::WebCustomDataType().Serialize(),
+ std::string(static_cast<const char*>(pickle.data()), pickle.size()));
+ clipboard()->WriteClipboardData(std::move(data));
+ clipboard()->ReadAvailableTypes(ClipboardBuffer::kCopyPaste,
+ /*data_dst=*/nullptr, &types);
+ EXPECT_EQ(std::vector<std::string>({"text/uri-list"}), UTF8Types(types));
+ EXPECT_FALSE(clipboard()->IsFormatAvailable(
+ ClipboardFormatType::FilenamesType(), ClipboardBuffer::kCopyPaste,
/*data_dst=*/nullptr));
}
diff --git a/chromium/ui/base/clipboard/clipboard_ozone.cc b/chromium/ui/base/clipboard/clipboard_ozone.cc
index 12e3371b4ee..62823f77885 100644
--- a/chromium/ui/base/clipboard/clipboard_ozone.cc
+++ b/chromium/ui/base/clipboard/clipboard_ozone.cc
@@ -13,7 +13,6 @@
#include "base/containers/contains.h"
#include "base/containers/flat_map.h"
#include "base/containers/span.h"
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/notreached.h"
#include "base/run_loop.h"
@@ -99,7 +98,8 @@ class ClipboardOzone::AsyncClipboardOzone {
platform_clipboard_->SetClipboardDataChangedCallback(
std::move(update_sequence_cb));
}
-
+ AsyncClipboardOzone(const AsyncClipboardOzone&) = delete;
+ AsyncClipboardOzone& operator=(const AsyncClipboardOzone&) = delete;
~AsyncClipboardOzone() = default;
bool IsSelectionBufferAvailable() const {
@@ -164,7 +164,8 @@ class ClipboardOzone::AsyncClipboardOzone {
}
}
- uint64_t GetSequenceNumber(ClipboardBuffer buffer) {
+ const ClipboardSequenceNumberToken& GetSequenceNumber(
+ ClipboardBuffer buffer) const {
return buffer == ClipboardBuffer::kCopyPaste ? clipboard_sequence_number_
: selection_sequence_number_;
}
@@ -275,9 +276,9 @@ class ClipboardOzone::AsyncClipboardOzone {
DCHECK(buffer == ClipboardBuffer::kCopyPaste ||
platform_clipboard_->IsSelectionBufferAvailable());
if (buffer == ClipboardBuffer::kCopyPaste)
- clipboard_sequence_number_++;
+ clipboard_sequence_number_ = ClipboardSequenceNumberToken();
else
- selection_sequence_number_++;
+ selection_sequence_number_ = ClipboardSequenceNumberToken();
ClipboardMonitor::GetInstance()->NotifyClipboardDataChanged();
}
@@ -296,12 +297,10 @@ class ClipboardOzone::AsyncClipboardOzone {
// Provides communication to a system clipboard under ozone level.
PlatformClipboard* const platform_clipboard_ = nullptr;
- uint64_t clipboard_sequence_number_ = 0;
- uint64_t selection_sequence_number_ = 0;
+ ClipboardSequenceNumberToken clipboard_sequence_number_;
+ ClipboardSequenceNumberToken selection_sequence_number_;
base::WeakPtrFactory<AsyncClipboardOzone> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(AsyncClipboardOzone);
};
// ClipboardOzone implementation.
@@ -329,7 +328,8 @@ DataTransferEndpoint* ClipboardOzone::GetSource(ClipboardBuffer buffer) const {
return it == data_src_.end() ? nullptr : it->second.get();
}
-uint64_t ClipboardOzone::GetSequenceNumber(ClipboardBuffer buffer) const {
+const ClipboardSequenceNumberToken& ClipboardOzone::GetSequenceNumber(
+ ClipboardBuffer buffer) const {
return async_clipboard_ozone_->GetSequenceNumber(buffer);
}
@@ -364,9 +364,9 @@ void ClipboardOzone::ReadAvailableTypes(
// Special handling for chromium/x-web-custom-data.
// We must read the data and deserialize it to find the list
// of mime types to report.
- if (mime_type == ClipboardFormatType::GetWebCustomDataType().GetName()) {
+ if (mime_type == ClipboardFormatType::WebCustomDataType().GetName()) {
auto data = async_clipboard_ozone_->ReadClipboardDataAndWait(
- buffer, ClipboardFormatType::GetWebCustomDataType().GetName());
+ buffer, ClipboardFormatType::WebCustomDataType().GetName());
ReadCustomDataTypes(data.data(), data.size(), types);
} else {
types->push_back(base::UTF8ToUTF16(mime_type));
@@ -468,8 +468,8 @@ void ClipboardOzone::ReadRTF(ClipboardBuffer buffer,
void ClipboardOzone::ReadPng(ClipboardBuffer buffer,
const DataTransferEndpoint* data_dst,
ReadPngCallback callback) const {
- // TODO(crbug.com/1201018): Implement this.
- NOTIMPLEMENTED();
+ RecordRead(ClipboardFormatMetric::kPng);
+ std::move(callback).Run(ReadPngInternal(buffer));
}
// TODO(crbug.com/1103194): |data_dst| should be supported.
@@ -477,7 +477,10 @@ void ClipboardOzone::ReadImage(ClipboardBuffer buffer,
const DataTransferEndpoint* data_dst,
ReadImageCallback callback) const {
RecordRead(ClipboardFormatMetric::kImage);
- std::move(callback).Run(ReadImageInternal(buffer));
+ auto png_data = ReadPngInternal(buffer);
+ SkBitmap bitmap;
+ gfx::PNGCodec::Decode(png_data.data(), png_data.size(), &bitmap);
+ std::move(callback).Run(bitmap);
}
// TODO(crbug.com/1103194): |data_dst| should be supported.
@@ -531,18 +534,8 @@ bool ClipboardOzone::IsSelectionBufferAvailable() const {
return async_clipboard_ozone_->IsSelectionBufferAvailable();
}
-// TODO(crbug.com/1103194): |data_src| should be supported
-void ClipboardOzone::WritePortableRepresentations(
- ClipboardBuffer buffer,
- const ObjectMap& objects,
- std::unique_ptr<DataTransferEndpoint> data_src) {
- DCHECK(CalledOnValidThread());
-
- async_clipboard_ozone_->PrepareForWriting();
- for (const auto& object : objects)
- DispatchPortableRepresentation(object.first, object.second);
- async_clipboard_ozone_->OfferData(buffer);
-
+void ClipboardOzone::WritePortableTextRepresentation(ClipboardBuffer buffer,
+ const ObjectMap& objects) {
// Just like Non-Backed/X11 implementation does, copy text data from the
// copy/paste selection to the primary selection.
if (buffer == ClipboardBuffer::kCopyPaste && IsSelectionBufferAvailable()) {
@@ -555,21 +548,24 @@ void ClipboardOzone::WritePortableRepresentations(
async_clipboard_ozone_->OfferData(ClipboardBuffer::kSelection);
}
}
-
- data_src_[buffer] = std::move(data_src);
}
// TODO(crbug.com/1103194): |data_src| should be supported
-void ClipboardOzone::WritePlatformRepresentations(
+void ClipboardOzone::WritePortableAndPlatformRepresentations(
ClipboardBuffer buffer,
+ const ObjectMap& objects,
std::vector<Clipboard::PlatformRepresentation> platform_representations,
std::unique_ptr<DataTransferEndpoint> data_src) {
DCHECK(CalledOnValidThread());
async_clipboard_ozone_->PrepareForWriting();
DispatchPlatformRepresentations(std::move(platform_representations));
+ for (const auto& object : objects)
+ DispatchPortableRepresentation(object.first, object.second);
async_clipboard_ozone_->OfferData(buffer);
+ WritePortableTextRepresentation(buffer, objects);
+
data_src_[buffer] = std::move(data_src);
}
@@ -637,16 +633,13 @@ void ClipboardOzone::WriteData(const ClipboardFormatType& format,
async_clipboard_ozone_->InsertData(std::move(data), {format.GetName()});
}
-SkBitmap ClipboardOzone::ReadImageInternal(ClipboardBuffer buffer) const {
+std::vector<uint8_t> ClipboardOzone::ReadPngInternal(
+ ClipboardBuffer buffer) const {
DCHECK(CalledOnValidThread());
- auto clipboard_data =
+ base::span<uint8_t> clipboard_data =
async_clipboard_ozone_->ReadClipboardDataAndWait(buffer, kMimeTypePNG);
- SkBitmap bitmap;
- if (!gfx::PNGCodec::Decode(clipboard_data.data(), clipboard_data.size(),
- &bitmap))
- return {};
- return SkBitmap(bitmap);
+ return std::vector<uint8_t>(clipboard_data.begin(), clipboard_data.end());
}
} // namespace ui
diff --git a/chromium/ui/base/clipboard/clipboard_ozone.h b/chromium/ui/base/clipboard/clipboard_ozone.h
index 730cf5d318c..a4b1f2a2788 100644
--- a/chromium/ui/base/clipboard/clipboard_ozone.h
+++ b/chromium/ui/base/clipboard/clipboard_ozone.h
@@ -9,7 +9,6 @@
#include <string>
#include <vector>
-#include "base/macros.h"
#include "ui/base/clipboard/clipboard.h"
namespace ui {
@@ -17,6 +16,10 @@ namespace ui {
// ClipboardOzone is not yet shipped in production. It is a work in progress
// for desktop Linux Wayland support.
class ClipboardOzone : public Clipboard {
+ public:
+ ClipboardOzone(const ClipboardOzone&) = delete;
+ ClipboardOzone& operator=(const ClipboardOzone&) = delete;
+
private:
friend class Clipboard;
@@ -26,7 +29,8 @@ class ClipboardOzone : public Clipboard {
// Clipboard overrides:
void OnPreShutdown() override;
DataTransferEndpoint* GetSource(ClipboardBuffer buffer) const override;
- uint64_t GetSequenceNumber(ClipboardBuffer buffer) const override;
+ const ClipboardSequenceNumberToken& GetSequenceNumber(
+ ClipboardBuffer buffer) const override;
bool IsFormatAvailable(const ClipboardFormatType& format,
ClipboardBuffer buffer,
const DataTransferEndpoint* data_dst) const override;
@@ -75,12 +79,11 @@ class ClipboardOzone : public Clipboard {
const DataTransferEndpoint* data_dst,
std::string* result) const override;
bool IsSelectionBufferAvailable() const override;
- void WritePortableRepresentations(
+ void WritePortableTextRepresentation(ClipboardBuffer buffer,
+ const ObjectMap& objects);
+ void WritePortableAndPlatformRepresentations(
ClipboardBuffer buffer,
const ObjectMap& objects,
- std::unique_ptr<DataTransferEndpoint> data_src) override;
- void WritePlatformRepresentations(
- ClipboardBuffer buffer,
std::vector<Clipboard::PlatformRepresentation> platform_representations,
std::unique_ptr<DataTransferEndpoint> data_src) override;
void WriteText(const char* text_data, size_t text_len) override;
@@ -101,15 +104,13 @@ class ClipboardOzone : public Clipboard {
const char* data_data,
size_t data_len) override;
- SkBitmap ReadImageInternal(ClipboardBuffer buffer) const;
+ std::vector<uint8_t> ReadPngInternal(ClipboardBuffer buffer) const;
class AsyncClipboardOzone;
std::unique_ptr<AsyncClipboardOzone> async_clipboard_ozone_;
base::flat_map<ClipboardBuffer, std::unique_ptr<DataTransferEndpoint>>
data_src_;
-
- DISALLOW_COPY_AND_ASSIGN(ClipboardOzone);
};
} // namespace ui
diff --git a/chromium/ui/base/clipboard/clipboard_sequence_number_token.h b/chromium/ui/base/clipboard/clipboard_sequence_number_token.h
new file mode 100644
index 00000000000..b76e1630f60
--- /dev/null
+++ b/chromium/ui/base/clipboard/clipboard_sequence_number_token.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_BASE_CLIPBOARD_CLIPBOARD_SEQUENCE_NUMBER_TOKEN_H_
+#define UI_BASE_CLIPBOARD_CLIPBOARD_SEQUENCE_NUMBER_TOKEN_H_
+
+#include "base/types/token_type.h"
+
+namespace ui {
+
+// Identifies a unique clipboard state. This can be used to version the data on
+// the clipboard and determine whether it has changed.
+using ClipboardSequenceNumberToken =
+ base::TokenType<class ClipboardSequenceNumberTokenTypeMarker>;
+
+} // namespace ui
+
+#endif // UI_BASE_CLIPBOARD_CLIPBOARD_SEQUENCE_NUMBER_TOKEN_H_
diff --git a/chromium/ui/base/clipboard/clipboard_test_template.h b/chromium/ui/base/clipboard/clipboard_test_template.h
index e89e6263a52..494b05094c7 100644
--- a/chromium/ui/base/clipboard/clipboard_test_template.h
+++ b/chromium/ui/base/clipboard/clipboard_test_template.h
@@ -20,6 +20,7 @@
#include <array>
#include <memory>
#include <string>
+#include <vector>
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
@@ -27,7 +28,6 @@
#include "base/run_loop.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
#include "build/chromecast_buildflags.h"
@@ -47,7 +47,7 @@
#include "ui/base/clipboard/test/test_clipboard.h"
#include "ui/base/data_transfer_policy/data_transfer_endpoint.h"
#include "ui/base/data_transfer_policy/data_transfer_policy_controller.h"
-#include "ui/base/ui_base_features.h"
+#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/half_float.h"
#include "url/origin.h"
@@ -112,13 +112,15 @@ class MockPolicyController : public DataTransferPolicyController {
MockPolicyController();
~MockPolicyController() override;
- MOCK_METHOD2(IsClipboardReadAllowed,
+ MOCK_METHOD3(IsClipboardReadAllowed,
bool(const DataTransferEndpoint* const data_src,
- const DataTransferEndpoint* const data_dst));
- MOCK_METHOD4(PasteIfAllowed,
+ const DataTransferEndpoint* const data_dst,
+ const absl::optional<size_t> size));
+ MOCK_METHOD5(PasteIfAllowed,
void(const DataTransferEndpoint* const data_src,
const DataTransferEndpoint* const data_dst,
- content::WebContents* web_contents,
+ const absl::optional<size_t> size,
+ content::RenderFrameHost* rfh,
base::OnceCallback<void(bool)> callback));
MOCK_METHOD3(IsDragDropAllowed,
bool(const DataTransferEndpoint* const data_src,
@@ -149,16 +151,22 @@ TYPED_TEST(ClipboardTest, ClearTest) {
EXPECT_TRUE(this->GetAvailableTypes(ClipboardBuffer::kCopyPaste).empty());
EXPECT_FALSE(this->clipboard().IsFormatAvailable(
- ClipboardFormatType::GetPlainTextType(), ClipboardBuffer::kCopyPaste,
+ ClipboardFormatType::PlainTextType(), ClipboardBuffer::kCopyPaste,
/* data_dst = */ nullptr));
#if defined(OS_WIN)
EXPECT_FALSE(this->clipboard().IsFormatAvailable(
- ClipboardFormatType::GetPlainTextAType(), ClipboardBuffer::kCopyPaste,
+ ClipboardFormatType::PlainTextAType(), ClipboardBuffer::kCopyPaste,
/* data_dst = */ nullptr));
#endif
}
-TYPED_TEST(ClipboardTest, TextTest) {
+// crbug.com/1224904: Flaky on Mac.
+#if defined(OS_MAC)
+#define MAYBE_TextTest DISABLED_TextTest
+#else
+#define MAYBE_TextTest TextTest
+#endif
+TYPED_TEST(ClipboardTest, MAYBE_TextTest) {
std::u16string text(u"This is a std::u16string!#$"), text_result;
std::string ascii_text;
@@ -180,11 +188,11 @@ TYPED_TEST(ClipboardTest, TextTest) {
}
#endif
EXPECT_TRUE(this->clipboard().IsFormatAvailable(
- ClipboardFormatType::GetPlainTextType(), ClipboardBuffer::kCopyPaste,
+ ClipboardFormatType::PlainTextType(), ClipboardBuffer::kCopyPaste,
/* data_dst = */ nullptr));
#if defined(OS_WIN)
EXPECT_TRUE(this->clipboard().IsFormatAvailable(
- ClipboardFormatType::GetPlainTextAType(), ClipboardBuffer::kCopyPaste,
+ ClipboardFormatType::PlainTextAType(), ClipboardBuffer::kCopyPaste,
/* data_dst = */ nullptr));
#endif
@@ -211,7 +219,7 @@ TYPED_TEST(ClipboardTest, HTMLTest) {
EXPECT_THAT(this->GetAvailableTypes(ClipboardBuffer::kCopyPaste),
Contains(ASCIIToUTF16(kMimeTypeHTML)));
EXPECT_TRUE(this->clipboard().IsFormatAvailable(
- ClipboardFormatType::GetHtmlType(), ClipboardBuffer::kCopyPaste,
+ ClipboardFormatType::HtmlType(), ClipboardBuffer::kCopyPaste,
/* data_dst = */ nullptr));
uint32_t fragment_start;
uint32_t fragment_end;
@@ -237,7 +245,7 @@ TYPED_TEST(ClipboardTest, SvgTest) {
}
EXPECT_TRUE(this->clipboard().IsFormatAvailable(
- ClipboardFormatType::GetSvgType(), ClipboardBuffer::kCopyPaste,
+ ClipboardFormatType::SvgType(), ClipboardBuffer::kCopyPaste,
/* data_dst = */ nullptr));
std::u16string markup_result;
@@ -264,7 +272,7 @@ TYPED_TEST(ClipboardTest, RTFTest) {
EXPECT_THAT(this->GetAvailableTypes(ClipboardBuffer::kCopyPaste),
Contains(ASCIIToUTF16(kMimeTypeRTF)));
EXPECT_TRUE(this->clipboard().IsFormatAvailable(
- ClipboardFormatType::GetRtfType(), ClipboardBuffer::kCopyPaste,
+ ClipboardFormatType::RtfType(), ClipboardBuffer::kCopyPaste,
/* data_dst = */ nullptr));
std::string result;
this->clipboard().ReadRTF(ClipboardBuffer::kCopyPaste,
@@ -302,17 +310,17 @@ TYPED_TEST(ClipboardTest, MultipleBufferTest) {
Contains(ASCIIToUTF16(kMimeTypeHTML)));
EXPECT_TRUE(this->clipboard().IsFormatAvailable(
- ClipboardFormatType::GetPlainTextType(), ClipboardBuffer::kCopyPaste,
+ ClipboardFormatType::PlainTextType(), ClipboardBuffer::kCopyPaste,
/* data_dst = */ nullptr));
EXPECT_FALSE(this->clipboard().IsFormatAvailable(
- ClipboardFormatType::GetPlainTextType(), ClipboardBuffer::kSelection,
+ ClipboardFormatType::PlainTextType(), ClipboardBuffer::kSelection,
/* data_dst = */ nullptr));
EXPECT_FALSE(this->clipboard().IsFormatAvailable(
- ClipboardFormatType::GetHtmlType(), ClipboardBuffer::kCopyPaste,
+ ClipboardFormatType::HtmlType(), ClipboardBuffer::kCopyPaste,
/* data_dst = */ nullptr));
EXPECT_TRUE(this->clipboard().IsFormatAvailable(
- ClipboardFormatType::GetHtmlType(), ClipboardBuffer::kSelection,
+ ClipboardFormatType::HtmlType(), ClipboardBuffer::kSelection,
/* data_dst = */ nullptr));
this->clipboard().ReadText(ClipboardBuffer::kCopyPaste,
@@ -345,7 +353,7 @@ TYPED_TEST(ClipboardTest, TrickyHTMLTest) {
EXPECT_THAT(this->GetAvailableTypes(ClipboardBuffer::kCopyPaste),
Contains(ASCIIToUTF16(kMimeTypeHTML)));
EXPECT_TRUE(this->clipboard().IsFormatAvailable(
- ClipboardFormatType::GetHtmlType(), ClipboardBuffer::kCopyPaste,
+ ClipboardFormatType::HtmlType(), ClipboardBuffer::kCopyPaste,
/* data_dst = */ nullptr));
uint32_t fragment_start;
uint32_t fragment_end;
@@ -362,9 +370,15 @@ TYPED_TEST(ClipboardTest, TrickyHTMLTest) {
#endif // defined(OS_WIN)
}
+// crbug.com/1224904: Flaky on Mac.
+#if defined(OS_MAC)
+#define MAYBE_UnicodeHTMLTest DISABLED_UnicodeHTMLTest
+#else
+#define MAYBE_UnicodeHTMLTest UnicodeHTMLTest
+#endif
// Some platforms store HTML as UTF-8 internally. Make sure fragment indices are
// adjusted appropriately when converting back to UTF-16.
-TYPED_TEST(ClipboardTest, UnicodeHTMLTest) {
+TYPED_TEST(ClipboardTest, MAYBE_UnicodeHTMLTest) {
std::u16string markup(u"<div>A ø 水</div>"), markup_result;
std::string url, url_result;
@@ -380,7 +394,7 @@ TYPED_TEST(ClipboardTest, UnicodeHTMLTest) {
EXPECT_THAT(this->GetAvailableTypes(ClipboardBuffer::kCopyPaste),
Contains(ASCIIToUTF16(kMimeTypeHTML)));
EXPECT_TRUE(this->clipboard().IsFormatAvailable(
- ClipboardFormatType::GetHtmlType(), ClipboardBuffer::kCopyPaste,
+ ClipboardFormatType::HtmlType(), ClipboardBuffer::kCopyPaste,
/* data_dst = */ nullptr));
uint32_t fragment_start;
uint32_t fragment_end;
@@ -407,7 +421,7 @@ TYPED_TEST(ClipboardTest, BookmarkTest) {
}
EXPECT_TRUE(this->clipboard().IsFormatAvailable(
- ClipboardFormatType::GetUrlType(), ClipboardBuffer::kCopyPaste,
+ ClipboardFormatType::UrlType(), ClipboardBuffer::kCopyPaste,
/* data_dst = */ nullptr));
this->clipboard().ReadBookmark(/* data_dst = */ nullptr, &title_result,
&url_result);
@@ -417,10 +431,14 @@ TYPED_TEST(ClipboardTest, BookmarkTest) {
#endif // !defined(OS_POSIX) || defined(OS_APPLE)
#if !defined(OS_ANDROID)
+// crbug.com/1224904: Flaky on Mac.
+#if defined(OS_MAC)
+#define MAYBE_FilenamesTest DISABLED_FilenamesTest
+#else
+#define MAYBE_FilenamesTest FilenamesTest
+#endif
// Filenames is not implemented in ClipboardAndroid.
-TYPED_TEST(ClipboardTest, FilenamesTest) {
- base::test::ScopedFeatureList features;
- features.InitWithFeatures({features::kClipboardFilenames}, {});
+TYPED_TEST(ClipboardTest, MAYBE_FilenamesTest) {
base::ScopedAllowBlockingForTesting allow_blocking;
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
@@ -434,7 +452,7 @@ TYPED_TEST(ClipboardTest, FilenamesTest) {
}
EXPECT_TRUE(this->clipboard().IsFormatAvailable(
- ClipboardFormatType::GetFilenamesType(), ClipboardBuffer::kCopyPaste,
+ ClipboardFormatType::FilenamesType(), ClipboardBuffer::kCopyPaste,
/* data_dst = */ nullptr));
std::vector<std::u16string> types;
@@ -451,7 +469,13 @@ TYPED_TEST(ClipboardTest, FilenamesTest) {
}
#endif // !defined(OS_ANDROID)
-TYPED_TEST(ClipboardTest, MultiFormatTest) {
+// crbug.com/1224904: Flaky on Mac.
+#if defined(OS_MAC)
+#define MAYBE_MultiFormatTest DISABLED_MultiFormatTest
+#else
+#define MAYBE_MultiFormatTest MultiFormatTest
+#endif
+TYPED_TEST(ClipboardTest, MAYBE_MultiFormatTest) {
std::u16string text(u"Hi!"), text_result;
std::u16string markup(u"<strong>Hi!</string>"), markup_result;
std::string url("http://www.example.com/"), url_result;
@@ -468,14 +492,14 @@ TYPED_TEST(ClipboardTest, MultiFormatTest) {
EXPECT_THAT(this->GetAvailableTypes(ClipboardBuffer::kCopyPaste),
Contains(ASCIIToUTF16(kMimeTypeText)));
EXPECT_TRUE(this->clipboard().IsFormatAvailable(
- ClipboardFormatType::GetHtmlType(), ClipboardBuffer::kCopyPaste,
+ ClipboardFormatType::HtmlType(), ClipboardBuffer::kCopyPaste,
/* data_dst = */ nullptr));
EXPECT_TRUE(this->clipboard().IsFormatAvailable(
- ClipboardFormatType::GetPlainTextType(), ClipboardBuffer::kCopyPaste,
+ ClipboardFormatType::PlainTextType(), ClipboardBuffer::kCopyPaste,
/* data_dst = */ nullptr));
#if defined(OS_WIN)
EXPECT_TRUE(this->clipboard().IsFormatAvailable(
- ClipboardFormatType::GetPlainTextAType(), ClipboardBuffer::kCopyPaste,
+ ClipboardFormatType::PlainTextAType(), ClipboardBuffer::kCopyPaste,
/* data_dst = */ nullptr));
#endif
uint32_t fragment_start;
@@ -510,11 +534,11 @@ TYPED_TEST(ClipboardTest, URLTest) {
EXPECT_THAT(this->GetAvailableTypes(ClipboardBuffer::kCopyPaste),
Contains(ASCIIToUTF16(kMimeTypeText)));
EXPECT_TRUE(this->clipboard().IsFormatAvailable(
- ClipboardFormatType::GetPlainTextType(), ClipboardBuffer::kCopyPaste,
+ ClipboardFormatType::PlainTextType(), ClipboardBuffer::kCopyPaste,
/* data_dst = */ nullptr));
#if defined(OS_WIN)
EXPECT_TRUE(this->clipboard().IsFormatAvailable(
- ClipboardFormatType::GetPlainTextAType(), ClipboardBuffer::kCopyPaste,
+ ClipboardFormatType::PlainTextAType(), ClipboardBuffer::kCopyPaste,
/* data_dst = */ nullptr));
#endif
std::u16string text_result;
@@ -544,24 +568,21 @@ namespace {
using U8x4 = std::array<uint8_t, 4>;
using F16x4 = std::array<gfx::HalfFloat, 4>;
-template <typename T>
-static void TestBitmapWrite(Clipboard* clipboard,
- const SkImageInfo& info,
- const T* bitmap_data,
- const U8x4* expect_data) {
+void WriteBitmap(Clipboard* clipboard,
+ const SkImageInfo& info,
+ const void* bitmap_data) {
{
- ScopedClipboardWriter scw(ClipboardBuffer::kCopyPaste);
+ ScopedClipboardWriter clipboard_writer(ClipboardBuffer::kCopyPaste);
SkBitmap bitmap;
ASSERT_TRUE(bitmap.setInfo(info));
- bitmap.setPixels(
- const_cast<void*>(reinterpret_cast<const void*>(bitmap_data)));
- scw.WriteImage(bitmap);
+ bitmap.setPixels(const_cast<void*>(bitmap_data));
+ clipboard_writer.WriteImage(bitmap);
}
+}
- EXPECT_TRUE(clipboard->IsFormatAvailable(ClipboardFormatType::GetBitmapType(),
- ClipboardBuffer::kCopyPaste,
- /* data_dst = */ nullptr));
- const SkBitmap& image = clipboard_test_util::ReadImage(clipboard);
+void AssertBitmapMatchesExpected(const SkBitmap& image,
+ const SkImageInfo& info,
+ const U8x4* expect_data) {
ASSERT_EQ(image.info().colorType(), kN32_SkColorType);
ASSERT_NE(image.info().alphaType(), kUnpremul_SkAlphaType);
EXPECT_EQ(gfx::Size(info.width(), info.height()),
@@ -576,9 +597,42 @@ static void TestBitmapWrite(Clipboard* clipboard,
}
}
+template <typename T>
+static void TestBitmapWrite(Clipboard* clipboard,
+ const SkImageInfo& info,
+ const T* bitmap_data,
+ const U8x4* expect_data) {
+ WriteBitmap(clipboard, info, reinterpret_cast<const void*>(bitmap_data));
+
+ EXPECT_TRUE(clipboard->IsFormatAvailable(ClipboardFormatType::BitmapType(),
+ ClipboardBuffer::kCopyPaste,
+ /* data_dst = */ nullptr));
+ const SkBitmap& image = clipboard_test_util::ReadImage(clipboard);
+ AssertBitmapMatchesExpected(image, info, expect_data);
+}
+
+template <typename T>
+static void TestBitmapWriteAndPngRead(Clipboard* clipboard,
+ const SkImageInfo& info,
+ const T* bitmap_data,
+ const U8x4* expect_data) {
+ WriteBitmap(clipboard, info, reinterpret_cast<const void*>(bitmap_data));
+
+ // Expect to be able to read images as either bitmaps or PNGs.
+ EXPECT_TRUE(clipboard->IsFormatAvailable(ClipboardFormatType::BitmapType(),
+ ClipboardBuffer::kCopyPaste,
+ /* data_dst = */ nullptr));
+ EXPECT_TRUE(clipboard->IsFormatAvailable(ClipboardFormatType::PngType(),
+ ClipboardBuffer::kCopyPaste,
+ /* data_dst = */ nullptr));
+ std::vector<uint8_t> result = clipboard_test_util::ReadPng(clipboard);
+ SkBitmap image;
+ gfx::PNGCodec::Decode(result.data(), result.size(), &image);
+ AssertBitmapMatchesExpected(image, info, expect_data);
+}
+
#if !defined(OS_ANDROID)
-// TODO(https://crbug.com/1056650): Re-enable these tests after fixing the root
-// cause. This test only fails on Android.
+// TODO(crbug.com/815537): Re-enable this test once death tests work on Android.
// Only kN32_SkColorType bitmaps are allowed in the clipboard to prevent
// surprising buffer overflows due to bits-per-pixel assumptions.
@@ -591,8 +645,15 @@ TYPED_TEST(ClipboardTest, Bitmap_F16_Premul) {
&kRGBAF16Premul, &kRGBAPremul),
"");
}
+#endif // !defined(OS_ANDROID)
-TYPED_TEST(ClipboardTest, Bitmap_N32_Premul) {
+// crbug.com/1224904: Flaky on Mac.
+#if defined(OS_MAC)
+#define MAYBE_Bitmap_N32_Premul DISABLED_Bitmap_N32_Premul
+#else
+#define MAYBE_Bitmap_N32_Premul Bitmap_N32_Premul
+#endif
+TYPED_TEST(ClipboardTest, MAYBE_Bitmap_N32_Premul) {
constexpr U8x4 b[4 * 3] = {
{0x26, 0x16, 0x06, 0x46}, {0x88, 0x59, 0x9f, 0xf6},
{0x37, 0x29, 0x3f, 0x79}, {0x86, 0xb9, 0x55, 0xfa},
@@ -603,6 +664,7 @@ TYPED_TEST(ClipboardTest, Bitmap_N32_Premul) {
};
TestBitmapWrite(&this->clipboard(), SkImageInfo::MakeN32Premul(4, 3), b, b);
}
+
TYPED_TEST(ClipboardTest, Bitmap_N32_Premul_2x7) {
constexpr U8x4 b[2 * 7] = {
{0x26, 0x16, 0x06, 0x46}, {0x88, 0x59, 0x9f, 0xf6},
@@ -615,8 +677,51 @@ TYPED_TEST(ClipboardTest, Bitmap_N32_Premul_2x7) {
};
TestBitmapWrite(&this->clipboard(), SkImageInfo::MakeN32Premul(2, 7), b, b);
}
+
+#if !defined(OS_ANDROID)
+// TODO(crbug.com/815537): Re-enable this test once death tests work on Android.
+
+// Only kN32_SkColorType bitmaps are allowed into the clipboard to prevent
+// surprising buffer overflows due to bits-per-pixel assumptions.
+TYPED_TEST(ClipboardTest, BitmapWriteAndPngRead_F16_Premul) {
+ constexpr F16x4 kRGBAF16Premul = {0x30c5, 0x2d86, 0x2606, 0x3464};
+ constexpr U8x4 kRGBAPremul = {0x26, 0x16, 0x06, 0x46};
+ EXPECT_DEATH(
+ TestBitmapWriteAndPngRead(
+ &this->clipboard(),
+ SkImageInfo::Make(1, 1, kRGBA_F16_SkColorType, kPremul_SkAlphaType),
+ &kRGBAF16Premul, &kRGBAPremul),
+ "");
+}
#endif // !defined(OS_ANDROID)
+TYPED_TEST(ClipboardTest, BitmapWriteAndPngRead_N32_Premul) {
+ constexpr U8x4 b[4 * 3] = {
+ {0x26, 0x16, 0x06, 0x46}, {0x88, 0x59, 0x9f, 0xf6},
+ {0x37, 0x29, 0x3f, 0x79}, {0x86, 0xb9, 0x55, 0xfa},
+ {0x52, 0x21, 0x77, 0x78}, {0x30, 0x2a, 0x69, 0x87},
+ {0x25, 0x2a, 0x32, 0x36}, {0x1b, 0x40, 0x20, 0x43},
+ {0x21, 0x8c, 0x84, 0x91}, {0x3c, 0x7b, 0x17, 0xc3},
+ {0x5c, 0x15, 0x46, 0x69}, {0x52, 0x19, 0x17, 0x64},
+ };
+ TestBitmapWriteAndPngRead(&this->clipboard(),
+ SkImageInfo::MakeN32Premul(4, 3), b, b);
+}
+
+TYPED_TEST(ClipboardTest, BitmapWriteAndPngRead_N32_Premul_2x7) {
+ constexpr U8x4 b[2 * 7] = {
+ {0x26, 0x16, 0x06, 0x46}, {0x88, 0x59, 0x9f, 0xf6},
+ {0x37, 0x29, 0x3f, 0x79}, {0x86, 0xb9, 0x55, 0xfa},
+ {0x52, 0x21, 0x77, 0x78}, {0x30, 0x2a, 0x69, 0x87},
+ {0x25, 0x2a, 0x32, 0x36}, {0x1b, 0x40, 0x20, 0x43},
+ {0x21, 0x8c, 0x84, 0x91}, {0x3c, 0x7b, 0x17, 0xc3},
+ {0x5c, 0x15, 0x46, 0x69}, {0x52, 0x19, 0x17, 0x64},
+ {0x13, 0x03, 0x91, 0xa6}, {0x3e, 0x32, 0x02, 0x83},
+ };
+ TestBitmapWriteAndPngRead(&this->clipboard(),
+ SkImageInfo::MakeN32Premul(2, 7), b, b);
+}
+
} // namespace
TYPED_TEST(ClipboardTest, PickleTest) {
@@ -637,7 +742,7 @@ TYPED_TEST(ClipboardTest, PickleTest) {
this->clipboard().ReadData(kFormat, /* data_dst = */ nullptr, &output);
ASSERT_FALSE(output.empty());
- base::Pickle read_pickle(output.data(), static_cast<int>(output.size()));
+ base::Pickle read_pickle(output.data(), output.size());
base::PickleIterator iter(read_pickle);
std::string unpickled_string;
ASSERT_TRUE(iter.ReadString(&unpickled_string));
@@ -674,7 +779,7 @@ TYPED_TEST(ClipboardTest, MultiplePickleTest) {
this->clipboard().ReadData(kFormat2, /* data_dst = */ nullptr, &output2);
ASSERT_FALSE(output2.empty());
- base::Pickle read_pickle2(output2.data(), static_cast<int>(output2.size()));
+ base::Pickle read_pickle2(output2.data(), output2.size());
base::PickleIterator iter2(read_pickle2);
std::string unpickled_string2;
ASSERT_TRUE(iter2.ReadString(&unpickled_string2));
@@ -697,18 +802,18 @@ TYPED_TEST(ClipboardTest, MultiplePickleTest) {
this->clipboard().ReadData(kFormat1, /* data_dst = */ nullptr, &output1);
ASSERT_FALSE(output1.empty());
- base::Pickle read_pickle1(output1.data(), static_cast<int>(output1.size()));
+ base::Pickle read_pickle1(output1.data(), output1.size());
base::PickleIterator iter1(read_pickle1);
std::string unpickled_string1;
ASSERT_TRUE(iter1.ReadString(&unpickled_string1));
EXPECT_EQ(payload1, unpickled_string1);
}
+// TODO(crbug.com/106449): Implement custom formats on other platforms.
+#if defined(OS_WIN)
TYPED_TEST(ClipboardTest, DataTest) {
const std::string kFormatString = "chromium/x-test-format";
const std::u16string kFormatString16 = u"chromium/x-test-format";
- const ClipboardFormatType kFormat =
- ClipboardFormatType::GetType(kFormatString);
const std::string payload = "test string";
base::span<const uint8_t> payload_span(
reinterpret_cast<const uint8_t*>(payload.data()), payload.size());
@@ -719,33 +824,28 @@ TYPED_TEST(ClipboardTest, DataTest) {
mojo_base::BigBuffer(payload_span));
}
- ASSERT_TRUE(this->clipboard().IsFormatAvailable(
- kFormat, ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr));
+ std::map<std::string, std::string> custom_format_names =
+ this->clipboard().ExtractCustomPlatformNames(ClipboardBuffer::kCopyPaste,
+ /* data_dst = */ nullptr);
+ EXPECT_TRUE(custom_format_names.find(kFormatString) !=
+ custom_format_names.end());
std::string output;
- this->clipboard().ReadData(kFormat, /* data_dst = */ nullptr, &output);
+ this->clipboard().ReadData(ClipboardFormatType::CustomPlatformType(
+ custom_format_names[kFormatString]),
+ /* data_dst = */ nullptr, &output);
EXPECT_EQ(payload, output);
}
-// TODO(https://crbug.com/1032161): Implement multiple raw types for
-// ClipboardInternal. This test currently doesn't run on ClipboardInternal
-// because ClipboardInternal only supports one raw type.
-#if (!defined(USE_AURA) || defined(OS_WIN) || defined(USE_OZONE) || \
- defined(USE_X11)) && \
- !BUILDFLAG(IS_CHROMEOS_ASH)
TYPED_TEST(ClipboardTest, MultipleDataTest) {
const std::string kFormatString1 = "chromium/x-test-format1";
const std::u16string kFormatString116 = u"chromium/x-test-format1";
- const ClipboardFormatType kFormat1 =
- ClipboardFormatType::GetType(kFormatString1);
const std::string payload1("test string1");
base::span<const uint8_t> payload_span1(
reinterpret_cast<const uint8_t*>(payload1.data()), payload1.size());
const std::string kFormatString2 = "chromium/x-test-format2";
const std::u16string kFormatString216 = u"chromium/x-test-format2";
- const ClipboardFormatType kFormat2 =
- ClipboardFormatType::GetType(kFormatString2);
const std::string payload2("test string2");
base::span<const uint8_t> payload_span2(
reinterpret_cast<const uint8_t*>(payload2.data()), payload2.size());
@@ -763,29 +863,112 @@ TYPED_TEST(ClipboardTest, MultipleDataTest) {
EXPECT_THAT(this->clipboard().ReadAvailablePlatformSpecificFormatNames(
ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr),
Contains(kFormatString116));
- EXPECT_TRUE(this->clipboard().IsFormatAvailable(
- kFormat1, ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr));
+ std::string custom_format_json;
+ this->clipboard().ReadData(ClipboardFormatType::WebCustomFormatMap(),
+ /* data_dst = */ nullptr, &custom_format_json);
+ std::map<std::string, std::string> custom_format_names =
+ this->clipboard().ExtractCustomPlatformNames(ClipboardBuffer::kCopyPaste,
+ /* data_dst = */ nullptr);
+ EXPECT_TRUE(custom_format_names.find(kFormatString1) !=
+ custom_format_names.end());
std::string output1;
- this->clipboard().ReadData(kFormat1, /* data_dst = */ nullptr, &output1);
+ this->clipboard().ReadData(ClipboardFormatType::CustomPlatformType(
+ custom_format_names[kFormatString1]),
+ /* data_dst = */ nullptr, &output1);
EXPECT_EQ(payload1, output1);
// Check format 2.
EXPECT_THAT(this->clipboard().ReadAvailablePlatformSpecificFormatNames(
ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr),
Contains(kFormatString216));
- EXPECT_TRUE(this->clipboard().IsFormatAvailable(
- kFormat2, ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr));
+ EXPECT_TRUE(custom_format_names.find(kFormatString2) !=
+ custom_format_names.end());
std::string output2;
- this->clipboard().ReadData(kFormat2, /* data_dst = */ nullptr, &output2);
+ this->clipboard().ReadData(ClipboardFormatType::CustomPlatformType(
+ custom_format_names[kFormatString2]),
+ /* data_dst = */ nullptr, &output2);
EXPECT_EQ(payload2, output2);
}
+
+TYPED_TEST(ClipboardTest, DataAndPortableFormatTest) {
+ const std::string kFormatString1 = "chromium/x-test-format1";
+ const std::u16string kFormatString116 = u"chromium/x-test-format1";
+ const std::string payload1("test string1");
+ base::span<const uint8_t> payload_span1(
+ reinterpret_cast<const uint8_t*>(payload1.data()), payload1.size());
+
+ const std::string kFormatString2 = "text/plain";
+ const std::u16string kFormatString216 = u"text/plain";
+ const std::string payload2("test string2");
+ base::span<const uint8_t> payload_span2(
+ reinterpret_cast<const uint8_t*>(payload2.data()), payload2.size());
+
+ {
+ ScopedClipboardWriter clipboard_writer(ClipboardBuffer::kCopyPaste);
+ // Both payloads should write successfully and not overwrite one another.
+ clipboard_writer.WriteData(kFormatString116,
+ mojo_base::BigBuffer(payload_span1));
+ clipboard_writer.WriteData(kFormatString216,
+ mojo_base::BigBuffer(payload_span2));
+ }
+
+ // Check format 1.
+ EXPECT_THAT(this->clipboard().ReadAvailablePlatformSpecificFormatNames(
+ ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr),
+ Contains(kFormatString116));
+ std::string custom_format_json;
+ this->clipboard().ReadData(ClipboardFormatType::WebCustomFormatMap(),
+ /* data_dst = */ nullptr, &custom_format_json);
+ std::map<std::string, std::string> custom_format_names =
+ this->clipboard().ExtractCustomPlatformNames(ClipboardBuffer::kCopyPaste,
+ /* data_dst = */ nullptr);
+ EXPECT_TRUE(custom_format_names.find(kFormatString1) !=
+ custom_format_names.end());
+ std::string output1;
+ this->clipboard().ReadData(ClipboardFormatType::CustomPlatformType(
+ custom_format_names[kFormatString1]),
+ /* data_dst = */ nullptr, &output1);
+ EXPECT_EQ(payload1, output1);
+
+ // Check format 2.
+ EXPECT_THAT(this->clipboard().ReadAvailablePlatformSpecificFormatNames(
+ ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr),
+ Contains(kFormatString216));
+ EXPECT_TRUE(custom_format_names.find(kFormatString2) !=
+ custom_format_names.end());
+ std::string output2;
+ this->clipboard().ReadData(ClipboardFormatType::CustomPlatformType(
+ custom_format_names[kFormatString2]),
+ /* data_dst = */ nullptr, &output2);
+ EXPECT_EQ(payload2, output2);
+}
+#endif
+
+// crbug.com/1224904: Flaky on Mac.
+#if defined(OS_MAC)
+#define MAYBE_ReadAvailablePlatformSpecificFormatNamesTest \
+ DISABLED_ReadAvailablePlatformSpecificFormatNamesTest
+#else
+#define MAYBE_ReadAvailablePlatformSpecificFormatNamesTest \
+ ReadAvailablePlatformSpecificFormatNamesTest
#endif
+TYPED_TEST(ClipboardTest, MAYBE_ReadAvailablePlatformSpecificFormatNamesTest) {
+ // We're testing platform-specific behavior, so use PlatformClipboardTest.
+ // TODO(https://crbug.com/1083050): The template shouldn't know about its
+ // instantiations. Move this information up using a flag, virtual method, or
+ // creating separate test files for different platforms.
+ std::string test_suite_name = ::testing::UnitTest::GetInstance()
+ ->current_test_info()
+ ->test_suite_name();
+ // TODO(crbug.com/106449): Update other platforms to support custom formats.
+ if (test_suite_name != std::string("ClipboardTest/PlatformClipboardTest"))
+ return;
-TYPED_TEST(ClipboardTest, ReadAvailablePlatformSpecificFormatNamesTest) {
std::u16string text = u"Test String";
std::string ascii_text;
{
ScopedClipboardWriter clipboard_writer(ClipboardBuffer::kCopyPaste);
+ // `WriteText` uses `ClipboardFormatType::PlainTextType` format.
clipboard_writer.WriteText(text);
}
@@ -795,7 +978,7 @@ TYPED_TEST(ClipboardTest, ReadAvailablePlatformSpecificFormatNamesTest) {
#if defined(OS_APPLE)
EXPECT_THAT(raw_types, Contains(u"public.utf8-plain-text"));
EXPECT_THAT(raw_types, Contains(u"NSStringPboardType"));
- EXPECT_EQ(raw_types.size(), static_cast<uint64_t>(2));
+ EXPECT_EQ(raw_types.size(), 2u);
// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
// of lacros-chrome is complete.
#elif defined(OS_LINUX) && !BUILDFLAG(IS_CHROMEOS_ASH) && \
@@ -807,22 +990,17 @@ TYPED_TEST(ClipboardTest, ReadAvailablePlatformSpecificFormatNamesTest) {
#if defined(USE_OZONE)
if (features::IsUsingOzonePlatform()) {
EXPECT_THAT(raw_types, Contains(ASCIIToUTF16(kMimeTypeTextUtf8)));
- EXPECT_EQ(raw_types.size(), static_cast<uint64_t>(5));
+ EXPECT_EQ(raw_types.size(), 5u);
return;
}
#endif // USE_OZONE
#if defined(USE_X11)
EXPECT_FALSE(features::IsUsingOzonePlatform());
- EXPECT_EQ(raw_types.size(), static_cast<uint64_t>(4));
+ EXPECT_EQ(raw_types.size(), 4u);
#endif // USE_X11
-#elif defined(OS_WIN)
- EXPECT_THAT(raw_types, Contains(u"CF_UNICODETEXT"));
- EXPECT_THAT(raw_types, Contains(u"CF_TEXT"));
- EXPECT_THAT(raw_types, Contains(u"CF_OEMTEXT"));
- EXPECT_EQ(raw_types.size(), static_cast<uint64_t>(3));
-#elif defined(USE_AURA) || defined(OS_ANDROID)
+#elif defined(USE_AURA) || defined(OS_ANDROID) || defined(OS_WIN)
EXPECT_THAT(raw_types, Contains(ASCIIToUTF16(kMimeTypeText)));
- EXPECT_EQ(raw_types.size(), static_cast<uint64_t>(1));
+ EXPECT_EQ(raw_types.size(), 1u);
#else
#error Unsupported platform
#endif
@@ -845,13 +1023,11 @@ TYPED_TEST(ClipboardTest, PlatformSpecificDataTest) {
return;
const std::string text = "test string";
+ const std::string kFormatString = "text/plain";
#if defined(OS_WIN)
- // Windows pre-defined ANSI text format.
- const std::string kFormatString = "CF_TEXT";
// Windows requires an extra '\0' at the end for a raw write.
const std::string kPlatformSpecificText = text + '\0';
#elif defined(USE_X11)
- const std::string kFormatString = "text/plain"; // X11 text format
const std::string kPlatformSpecificText = text;
#endif
base::span<const uint8_t> text_span(
@@ -863,38 +1039,18 @@ TYPED_TEST(ClipboardTest, PlatformSpecificDataTest) {
mojo_base::BigBuffer(text_span));
}
- const std::vector<std::u16string> raw_types =
- this->clipboard().ReadAvailablePlatformSpecificFormatNames(
- ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr);
-
- EXPECT_THAT(raw_types, Contains(ASCIIToUTF16(kFormatString)));
-
-#if defined(OS_WIN)
- // Only Windows ClipboardFormatType recognizes ANSI formats.
- EXPECT_TRUE(this->clipboard().IsFormatAvailable(
- ClipboardFormatType::GetPlainTextAType(), ClipboardBuffer::kCopyPaste,
- /* data_dst = */ nullptr));
-#endif // defined(OS_WIN)
-
- EXPECT_TRUE(this->clipboard().IsFormatAvailable(
- ClipboardFormatType::GetPlainTextType(), ClipboardBuffer::kCopyPaste,
- /* data_dst = */ nullptr));
-
- std::string text_result;
- this->clipboard().ReadAsciiText(ClipboardBuffer::kCopyPaste,
- /* data_dst = */ nullptr, &text_result);
- EXPECT_EQ(text_result, text);
- // Windows will automatically convert CF_TEXT to its UNICODE version.
- EXPECT_TRUE(this->clipboard().IsFormatAvailable(
- ClipboardFormatType::GetPlainTextType(), ClipboardBuffer::kCopyPaste,
- /* data_dst = */ nullptr));
- std::u16string text_result16;
- this->clipboard().ReadText(ClipboardBuffer::kCopyPaste,
- /* data_dst = */ nullptr, &text_result16);
- EXPECT_EQ(text_result16, base::ASCIIToUTF16(text));
+ std::string custom_format_json;
+ this->clipboard().ReadData(ClipboardFormatType::WebCustomFormatMap(),
+ /* data_dst = */ nullptr, &custom_format_json);
+ std::map<std::string, std::string> custom_format_names =
+ this->clipboard().ExtractCustomPlatformNames(ClipboardBuffer::kCopyPaste,
+ /* data_dst = */ nullptr);
+ EXPECT_TRUE(custom_format_names.find(kFormatString) !=
+ custom_format_names.end());
std::string platform_specific_result;
- this->clipboard().ReadData(ClipboardFormatType::GetType(kFormatString),
+ this->clipboard().ReadData(ClipboardFormatType::CustomPlatformType(
+ custom_format_names[kFormatString]),
/* data_dst = */ nullptr,
&platform_specific_result);
EXPECT_EQ(platform_specific_result, kPlatformSpecificText);
@@ -917,7 +1073,7 @@ TYPED_TEST(ClipboardTest, HyperlinkTest) {
}
EXPECT_TRUE(this->clipboard().IsFormatAvailable(
- ClipboardFormatType::GetHtmlType(), ClipboardBuffer::kCopyPaste,
+ ClipboardFormatType::HtmlType(), ClipboardBuffer::kCopyPaste,
/* data_dst = */ nullptr));
uint32_t fragment_start;
uint32_t fragment_end;
@@ -937,8 +1093,8 @@ TYPED_TEST(ClipboardTest, WebSmartPasteTest) {
}
EXPECT_TRUE(this->clipboard().IsFormatAvailable(
- ClipboardFormatType::GetWebKitSmartPasteType(),
- ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr));
+ ClipboardFormatType::WebKitSmartPasteType(), ClipboardBuffer::kCopyPaste,
+ /* data_dst = */ nullptr));
}
#if defined(OS_WIN) // Windows only tests.
@@ -1011,7 +1167,7 @@ TYPED_TEST(ClipboardTest, WriteEverything) {
// written to.
// TODO(dcheng): Add a version to test ClipboardBuffer::kSelection.
TYPED_TEST(ClipboardTest, GetSequenceNumber) {
- const uint64_t first_sequence_number =
+ const ClipboardSequenceNumberToken first_sequence_number =
this->clipboard().GetSequenceNumber(ClipboardBuffer::kCopyPaste);
{
@@ -1023,7 +1179,7 @@ TYPED_TEST(ClipboardTest, GetSequenceNumber) {
// the message loop to make sure we get the notification.
base::RunLoop().RunUntilIdle();
- const uint64_t second_sequence_number =
+ const ClipboardSequenceNumberToken second_sequence_number =
this->clipboard().GetSequenceNumber(ClipboardBuffer::kCopyPaste);
EXPECT_NE(first_sequence_number, second_sequence_number);
@@ -1064,7 +1220,7 @@ TYPED_TEST(ClipboardTest, WriteHyperlinkEmptyParams) {
TYPED_TEST(ClipboardTest, WritePickledData) {
ScopedClipboardWriter scw(ClipboardBuffer::kCopyPaste);
- scw.WritePickledData(base::Pickle(), ClipboardFormatType::GetPlainTextType());
+ scw.WritePickledData(base::Pickle(), ClipboardFormatType::PlainTextType());
}
TYPED_TEST(ClipboardTest, WriteImageEmptyParams) {
diff --git a/chromium/ui/base/clipboard/clipboard_util_mac_unittest.mm b/chromium/ui/base/clipboard/clipboard_util_mac_unittest.mm
index 13a2ef789a9..1156d26a91e 100644
--- a/chromium/ui/base/clipboard/clipboard_util_mac_unittest.mm
+++ b/chromium/ui/base/clipboard/clipboard_util_mac_unittest.mm
@@ -6,6 +6,7 @@
#include "base/mac/scoped_nsobject.h"
#include "base/memory/ref_counted.h"
+#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/gtest_mac.h"
#include "testing/platform_test.h"
@@ -18,13 +19,28 @@ class ClipboardUtilMacTest : public PlatformTest {
public:
ClipboardUtilMacTest() { }
- NSDictionary* DictionaryFromPasteboard(NSPasteboard* pboard) {
- NSArray* types = [pboard types];
- NSMutableDictionary* data = [NSMutableDictionary dictionary];
- for (NSString* type in types) {
- data[type] = [pboard dataForType:type];
+ // Given a pasteboard, returns a dictionary of the contents of the pasteboard
+ // for use in deep comparisons. This fully unpacks any plist-encoded items.
+ NSDictionary* DictionaryFromPasteboardForDeepComparisons(
+ NSPasteboard* pboard) {
+ NSMutableDictionary* result = [NSMutableDictionary dictionary];
+ for (NSString* type in [pboard types]) {
+ NSData* data = [pboard dataForType:type];
+ // Try to unpack the data as a plist, and if it succeeds, use that in the
+ // resulting dictionary rather than the raw NSData. This is needed because
+ // plists have multiple encodings, and the comparison should be made on
+ // the underlying data rather than the specific encoding used by the OS.
+ NSDictionary* unpacked_data = [NSPropertyListSerialization
+ propertyListWithData:data
+ options:NSPropertyListImmutable
+ format:nil
+ error:nil];
+ if (unpacked_data)
+ result[type] = unpacked_data;
+ else
+ result[type] = data;
}
- return data;
+ return result;
}
};
@@ -126,8 +142,10 @@ TEST_F(ClipboardUtilMacTest, CompareToWriteToPasteboard) {
scoped_refptr<UniquePasteboard> pboard = new UniquePasteboard;
[pboard->get() setDataForURL:urlString title:urlString];
- NSDictionary* data1 = DictionaryFromPasteboard(pasteboard->get());
- NSDictionary* data2 = DictionaryFromPasteboard(pboard->get());
+ NSDictionary* data1 =
+ DictionaryFromPasteboardForDeepComparisons(pasteboard->get());
+ NSDictionary* data2 =
+ DictionaryFromPasteboardForDeepComparisons(pboard->get());
EXPECT_NSEQ(data1, data2);
}
diff --git a/chromium/ui/base/clipboard/clipboard_util_win.cc b/chromium/ui/base/clipboard/clipboard_util_win.cc
index 747923cb6d4..4acce28b16a 100644
--- a/chromium/ui/base/clipboard/clipboard_util_win.cc
+++ b/chromium/ui/base/clipboard/clipboard_util_win.cc
@@ -11,9 +11,9 @@
#include <limits>
#include <utility>
+#include "base/cxx17_backports.h"
#include "base/files/file_util.h"
#include "base/logging.h"
-#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/sys_string_conversions.h"
@@ -55,7 +55,7 @@ bool GetUrlFromHDrop(IDataObject* data_object,
bool success = false;
STGMEDIUM medium;
- if (!GetData(data_object, ClipboardFormatType::GetCFHDropType(), &medium))
+ if (!GetData(data_object, ClipboardFormatType::CFHDropType(), &medium))
return false;
{
@@ -250,13 +250,12 @@ HGLOBAL CopyFileContentsToHGlobal(IDataObject* data_object, LONG index) {
DCHECK(data_object);
HGLOBAL hdata = nullptr;
- if (!HasData(data_object,
- ClipboardFormatType::GetFileContentAtIndexType(index)))
+ if (!HasData(data_object, ClipboardFormatType::FileContentAtIndexType(index)))
return hdata;
STGMEDIUM content;
- if (!GetData(data_object,
- ClipboardFormatType::GetFileContentAtIndexType(index), &content))
+ if (!GetData(data_object, ClipboardFormatType::FileContentAtIndexType(index),
+ &content))
return hdata;
HRESULT hr = S_OK;
@@ -365,7 +364,7 @@ struct FileGroupDescriptorData;
template <>
struct FileGroupDescriptorData<FILEGROUPDESCRIPTORW> {
static bool get(IDataObject* data_object, STGMEDIUM* medium) {
- return GetData(data_object, ClipboardFormatType::GetFileDescriptorType(),
+ return GetData(data_object, ClipboardFormatType::FileDescriptorType(),
medium);
}
};
@@ -373,7 +372,7 @@ struct FileGroupDescriptorData<FILEGROUPDESCRIPTORW> {
template <>
struct FileGroupDescriptorData<FILEGROUPDESCRIPTORA> {
static bool get(IDataObject* data_object, STGMEDIUM* medium) {
- return GetData(data_object, ClipboardFormatType::GetFileDescriptorAType(),
+ return GetData(data_object, ClipboardFormatType::FileDescriptorAType(),
medium);
}
};
@@ -448,46 +447,45 @@ bool GetFileNameFromFirstDescriptor(IDataObject* data_object,
bool ClipboardUtil::HasUrl(IDataObject* data_object, bool convert_filenames) {
DCHECK(data_object);
- return HasData(data_object, ClipboardFormatType::GetMozUrlType()) ||
- HasData(data_object, ClipboardFormatType::GetUrlType()) ||
- HasData(data_object, ClipboardFormatType::GetUrlAType()) ||
+ return HasData(data_object, ClipboardFormatType::MozUrlType()) ||
+ HasData(data_object, ClipboardFormatType::UrlType()) ||
+ HasData(data_object, ClipboardFormatType::UrlAType()) ||
(convert_filenames && HasFilenames(data_object));
}
bool ClipboardUtil::HasFilenames(IDataObject* data_object) {
DCHECK(data_object);
- return HasData(data_object, ClipboardFormatType::GetCFHDropType()) ||
- HasData(data_object, ClipboardFormatType::GetFilenameType()) ||
- HasData(data_object, ClipboardFormatType::GetFilenameAType());
+ return HasData(data_object, ClipboardFormatType::CFHDropType()) ||
+ HasData(data_object, ClipboardFormatType::FilenameType()) ||
+ HasData(data_object, ClipboardFormatType::FilenameAType());
}
bool ClipboardUtil::HasVirtualFilenames(IDataObject* data_object) {
DCHECK(data_object);
// Favor real files on the file system over virtual files.
return !HasFilenames(data_object) &&
- HasData(data_object,
- ClipboardFormatType::GetFileContentAtIndexType(0)) &&
- (HasData(data_object, ClipboardFormatType::GetFileDescriptorType()) ||
- HasData(data_object, ClipboardFormatType::GetFileDescriptorAType()));
+ HasData(data_object, ClipboardFormatType::FileContentAtIndexType(0)) &&
+ (HasData(data_object, ClipboardFormatType::FileDescriptorType()) ||
+ HasData(data_object, ClipboardFormatType::FileDescriptorAType()));
}
bool ClipboardUtil::HasFileContents(IDataObject* data_object) {
DCHECK(data_object);
- return HasData(data_object, ClipboardFormatType::GetFileContentZeroType()) &&
- (HasData(data_object, ClipboardFormatType::GetFileDescriptorType()) ||
- HasData(data_object, ClipboardFormatType::GetFileDescriptorAType()));
+ return HasData(data_object, ClipboardFormatType::FileContentZeroType()) &&
+ (HasData(data_object, ClipboardFormatType::FileDescriptorType()) ||
+ HasData(data_object, ClipboardFormatType::FileDescriptorAType()));
}
bool ClipboardUtil::HasHtml(IDataObject* data_object) {
DCHECK(data_object);
- return HasData(data_object, ClipboardFormatType::GetHtmlType()) ||
- HasData(data_object, ClipboardFormatType::GetTextHtmlType());
+ return HasData(data_object, ClipboardFormatType::HtmlType()) ||
+ HasData(data_object, ClipboardFormatType::TextHtmlType());
}
bool ClipboardUtil::HasPlainText(IDataObject* data_object) {
DCHECK(data_object);
- return HasData(data_object, ClipboardFormatType::GetPlainTextType()) ||
- HasData(data_object, ClipboardFormatType::GetPlainTextAType());
+ return HasData(data_object, ClipboardFormatType::PlainTextType()) ||
+ HasData(data_object, ClipboardFormatType::PlainTextAType());
}
bool ClipboardUtil::GetUrl(IDataObject* data_object,
@@ -503,8 +501,8 @@ bool ClipboardUtil::GetUrl(IDataObject* data_object,
if (GetUrlFromHDrop(data_object, url, title))
return true;
- if (GetData(data_object, ClipboardFormatType::GetMozUrlType(), &store) ||
- GetData(data_object, ClipboardFormatType::GetUrlType(), &store)) {
+ if (GetData(data_object, ClipboardFormatType::MozUrlType(), &store) ||
+ GetData(data_object, ClipboardFormatType::UrlType(), &store)) {
{
// Mozilla URL format or Unicode URL
base::win::ScopedHGlobal<wchar_t*> data(store.hGlobal);
@@ -514,7 +512,7 @@ bool ClipboardUtil::GetUrl(IDataObject* data_object,
return url->is_valid();
}
- if (GetData(data_object, ClipboardFormatType::GetUrlAType(), &store)) {
+ if (GetData(data_object, ClipboardFormatType::UrlAType(), &store)) {
{
// URL using ASCII
base::win::ScopedHGlobal<char*> data(store.hGlobal);
@@ -543,7 +541,7 @@ bool ClipboardUtil::GetFilenames(IDataObject* data_object,
return false;
STGMEDIUM medium;
- if (GetData(data_object, ClipboardFormatType::GetCFHDropType(), &medium)) {
+ if (GetData(data_object, ClipboardFormatType::CFHDropType(), &medium)) {
{
base::win::ScopedHGlobal<HDROP> hdrop(medium.hGlobal);
if (!hdrop.get())
@@ -562,7 +560,7 @@ bool ClipboardUtil::GetFilenames(IDataObject* data_object,
return !filenames->empty();
}
- if (GetData(data_object, ClipboardFormatType::GetFilenameType(), &medium)) {
+ if (GetData(data_object, ClipboardFormatType::FilenameType(), &medium)) {
{
// filename using Unicode
base::win::ScopedHGlobal<wchar_t*> data(medium.hGlobal);
@@ -573,7 +571,7 @@ bool ClipboardUtil::GetFilenames(IDataObject* data_object,
return true;
}
- if (GetData(data_object, ClipboardFormatType::GetFilenameAType(), &medium)) {
+ if (GetData(data_object, ClipboardFormatType::FilenameAType(), &medium)) {
{
// filename using ASCII
base::win::ScopedHGlobal<char*> data(medium.hGlobal);
@@ -692,7 +690,7 @@ bool ClipboardUtil::GetPlainText(IDataObject* data_object,
return false;
STGMEDIUM store;
- if (GetData(data_object, ClipboardFormatType::GetPlainTextType(), &store)) {
+ if (GetData(data_object, ClipboardFormatType::PlainTextType(), &store)) {
{
// Unicode text
base::win::ScopedHGlobal<wchar_t*> data(store.hGlobal);
@@ -702,7 +700,7 @@ bool ClipboardUtil::GetPlainText(IDataObject* data_object,
return true;
}
- if (GetData(data_object, ClipboardFormatType::GetPlainTextAType(), &store)) {
+ if (GetData(data_object, ClipboardFormatType::PlainTextAType(), &store)) {
{
// ASCII text
base::win::ScopedHGlobal<char*> data(store.hGlobal);
@@ -729,8 +727,8 @@ bool ClipboardUtil::GetHtml(IDataObject* data_object,
DCHECK(data_object && html && base_url);
STGMEDIUM store;
- if (HasData(data_object, ClipboardFormatType::GetHtmlType()) &&
- GetData(data_object, ClipboardFormatType::GetHtmlType(), &store)) {
+ if (HasData(data_object, ClipboardFormatType::HtmlType()) &&
+ GetData(data_object, ClipboardFormatType::HtmlType(), &store)) {
{
// MS CF html
base::win::ScopedHGlobal<char*> data(store.hGlobal);
@@ -743,10 +741,10 @@ bool ClipboardUtil::GetHtml(IDataObject* data_object,
return true;
}
- if (!HasData(data_object, ClipboardFormatType::GetTextHtmlType()))
+ if (!HasData(data_object, ClipboardFormatType::TextHtmlType()))
return false;
- if (!GetData(data_object, ClipboardFormatType::GetTextHtmlType(), &store))
+ if (!GetData(data_object, ClipboardFormatType::TextHtmlType(), &store))
return false;
{
@@ -768,7 +766,7 @@ bool ClipboardUtil::GetFileContents(IDataObject* data_object,
STGMEDIUM content;
// The call to GetData can be very slow depending on what is in
// |data_object|.
- if (GetData(data_object, ClipboardFormatType::GetFileContentZeroType(),
+ if (GetData(data_object, ClipboardFormatType::FileContentZeroType(),
&content)) {
if (TYMED_HGLOBAL == content.tymed) {
base::win::ScopedHGlobal<char*> data(content.hGlobal);
@@ -800,12 +798,11 @@ bool ClipboardUtil::GetWebCustomData(
std::unordered_map<std::u16string, std::u16string>* custom_data) {
DCHECK(data_object && custom_data);
- if (!HasData(data_object, ClipboardFormatType::GetWebCustomDataType()))
+ if (!HasData(data_object, ClipboardFormatType::WebCustomDataType()))
return false;
STGMEDIUM store;
- if (GetData(data_object, ClipboardFormatType::GetWebCustomDataType(),
- &store)) {
+ if (GetData(data_object, ClipboardFormatType::WebCustomDataType(), &store)) {
{
base::win::ScopedHGlobal<char*> data(store.hGlobal);
ReadCustomDataIntoMap(data.get(), data.Size(), custom_data);
diff --git a/chromium/ui/base/clipboard/clipboard_win.cc b/chromium/ui/base/clipboard/clipboard_win.cc
index 868de231d10..9422954679f 100644
--- a/chromium/ui/base/clipboard/clipboard_win.cc
+++ b/chromium/ui/base/clipboard/clipboard_win.cc
@@ -10,16 +10,15 @@
#include <objidl.h>
#include <shellapi.h>
#include <shlobj.h>
+#include <cstdint>
+#include <vector>
#include "base/bind.h"
#include "base/check_op.h"
-#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/lazy_instance.h"
-#include "base/macros.h"
#include "base/notreached.h"
#include "base/numerics/safe_conversions.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
@@ -40,7 +39,6 @@
#include "ui/base/clipboard/clipboard_util_win.h"
#include "ui/base/clipboard/custom_data_helper.h"
#include "ui/base/data_transfer_policy/data_transfer_endpoint.h"
-#include "ui/base/ui_base_features.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/geometry/size.h"
@@ -56,7 +54,8 @@ class AnonymousImpersonator {
AnonymousImpersonator() {
must_revert_ = ::ImpersonateAnonymousToken(::GetCurrentThread());
}
-
+ AnonymousImpersonator(const AnonymousImpersonator&) = delete;
+ AnonymousImpersonator& operator=(const AnonymousImpersonator&) = delete;
~AnonymousImpersonator() {
if (must_revert_)
::RevertToSelf();
@@ -64,7 +63,6 @@ class AnonymousImpersonator {
private:
BOOL must_revert_;
- DISALLOW_COPY_AND_ASSIGN(AnonymousImpersonator);
};
// A scoper to manage acquiring and automatically releasing the clipboard.
@@ -225,16 +223,12 @@ void TrimAfterNull(StringType* result) {
}
bool ReadFilenamesAvailable() {
- // Only support filenames if chrome://flags#clipboard-filenames is enabled.
- if (!base::FeatureList::IsEnabled(features::kClipboardFilenames))
- return false;
-
return ::IsClipboardFormatAvailable(
- ClipboardFormatType::GetCFHDropType().ToFormatEtc().cfFormat) ||
+ ClipboardFormatType::CFHDropType().ToFormatEtc().cfFormat) ||
::IsClipboardFormatAvailable(
- ClipboardFormatType::GetFilenameType().ToFormatEtc().cfFormat) ||
+ ClipboardFormatType::FilenameType().ToFormatEtc().cfFormat) ||
::IsClipboardFormatAvailable(
- ClipboardFormatType::GetFilenameAType().ToFormatEtc().cfFormat);
+ ClipboardFormatType::FilenameAType().ToFormatEtc().cfFormat);
}
} // namespace
@@ -262,9 +256,16 @@ DataTransferEndpoint* ClipboardWin::GetSource(ClipboardBuffer buffer) const {
return nullptr;
}
-uint64_t ClipboardWin::GetSequenceNumber(ClipboardBuffer buffer) const {
+const ClipboardSequenceNumberToken& ClipboardWin::GetSequenceNumber(
+ ClipboardBuffer buffer) const {
DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
- return ::GetClipboardSequenceNumber();
+
+ DWORD sequence_number = ::GetClipboardSequenceNumber();
+ if (sequence_number != clipboard_sequence_.sequence_number) {
+ // Generate a unique token associated with the current sequence number.
+ clipboard_sequence_ = {sequence_number, ClipboardSequenceNumberToken()};
+ }
+ return clipboard_sequence_.token;
}
// |data_dst| is not used. It's only passed to be consistent with other
@@ -274,8 +275,19 @@ bool ClipboardWin::IsFormatAvailable(
ClipboardBuffer buffer,
const DataTransferEndpoint* data_dst) const {
DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
- if (format == ClipboardFormatType::GetFilenameType())
+ if (format == ClipboardFormatType::FilenameType())
return ReadFilenamesAvailable();
+ // Chrome can retrieve an image from the clipboard as either a bitmap or PNG.
+ if (format == ClipboardFormatType::PngType() ||
+ format == ClipboardFormatType::BitmapType()) {
+ return ::IsClipboardFormatAvailable(
+ ClipboardFormatType::PngType().ToFormatEtc().cfFormat) !=
+ FALSE ||
+ ::IsClipboardFormatAvailable(
+ ClipboardFormatType::BitmapType().ToFormatEtc().cfFormat) !=
+ FALSE;
+ }
+
return ::IsClipboardFormatAvailable(format.ToFormatEtc().cfFormat) != FALSE;
}
@@ -298,13 +310,13 @@ void ClipboardWin::ReadAvailableTypes(
types->clear();
if (::IsClipboardFormatAvailable(
- ClipboardFormatType::GetPlainTextAType().ToFormatEtc().cfFormat))
+ ClipboardFormatType::PlainTextAType().ToFormatEtc().cfFormat))
types->push_back(base::UTF8ToUTF16(kMimeTypeText));
if (::IsClipboardFormatAvailable(
- ClipboardFormatType::GetHtmlType().ToFormatEtc().cfFormat))
+ ClipboardFormatType::HtmlType().ToFormatEtc().cfFormat))
types->push_back(base::UTF8ToUTF16(kMimeTypeHTML));
if (::IsClipboardFormatAvailable(
- ClipboardFormatType::GetRtfType().ToFormatEtc().cfFormat))
+ ClipboardFormatType::RtfType().ToFormatEtc().cfFormat))
types->push_back(base::UTF8ToUTF16(kMimeTypeRTF));
if (::IsClipboardFormatAvailable(CF_DIB))
types->push_back(base::UTF8ToUTF16(kMimeTypePNG));
@@ -317,7 +329,7 @@ void ClipboardWin::ReadAvailableTypes(
return;
HANDLE hdata = ::GetClipboardData(
- ClipboardFormatType::GetWebCustomDataType().ToFormatEtc().cfFormat);
+ ClipboardFormatType::WebCustomDataType().ToFormatEtc().cfFormat);
if (!hdata)
return;
@@ -342,12 +354,18 @@ ClipboardWin::ReadAvailablePlatformSpecificFormatNames(
if (!clipboard.Acquire(GetClipboardWindow()))
return {};
+ // Check if we have any custom formats in the clipboard.
+ std::map<std::string, std::string> custom_format_names =
+ ExtractCustomPlatformNames(buffer, data_dst);
+ for (const auto& items : custom_format_names) {
+ types.push_back(base::ASCIIToUTF16(items.first));
+ }
UINT cf_format = 0;
cf_format = ::EnumClipboardFormats(cf_format);
while (cf_format) {
std::string type_name = ClipboardFormatType(cf_format).GetName();
if (!type_name.empty())
- types.push_back(base::UTF8ToUTF16(type_name));
+ types.push_back(base::ASCIIToUTF16(type_name));
cf_format = ::EnumClipboardFormats(cf_format);
}
return types;
@@ -436,7 +454,7 @@ void ClipboardWin::ReadHTML(ClipboardBuffer buffer,
return;
HANDLE data = ::GetClipboardData(
- ClipboardFormatType::GetHtmlType().ToFormatEtc().cfFormat);
+ ClipboardFormatType::HtmlType().ToFormatEtc().cfFormat);
if (!data)
return;
@@ -461,9 +479,8 @@ void ClipboardWin::ReadHTML(ClipboardBuffer buffer,
if (start_index < html_start || end_index < start_index)
return;
- std::vector<size_t> offsets;
- offsets.push_back(start_index - html_start);
- offsets.push_back(end_index - html_start);
+ std::vector<size_t> offsets = {start_index - html_start,
+ end_index - html_start};
markup->assign(base::UTF8ToUTF16AndAdjustOffsets(cf_html.data() + html_start,
&offsets));
// Ensure the Fragment points within the string; see https://crbug.com/607181.
@@ -481,7 +498,7 @@ void ClipboardWin::ReadSvg(ClipboardBuffer buffer,
RecordRead(ClipboardFormatMetric::kSvg);
std::string data;
- ReadData(ClipboardFormatType::GetSvgType(), data_dst, &data);
+ ReadData(ClipboardFormatType::SvgType(), data_dst, &data);
result->assign(reinterpret_cast<const char16_t*>(data.data()),
data.size() / sizeof(char16_t));
@@ -496,7 +513,7 @@ void ClipboardWin::ReadRTF(ClipboardBuffer buffer,
DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
RecordRead(ClipboardFormatMetric::kRtf);
- ReadData(ClipboardFormatType::GetRtfType(), data_dst, result);
+ ReadData(ClipboardFormatType::RtfType(), data_dst, result);
TrimAfterNull(result);
}
@@ -505,8 +522,16 @@ void ClipboardWin::ReadRTF(ClipboardBuffer buffer,
void ClipboardWin::ReadPng(ClipboardBuffer buffer,
const DataTransferEndpoint* data_dst,
ReadPngCallback callback) const {
- // TODO(crbug.com/1201018): Implement this.
- NOTIMPLEMENTED();
+ RecordRead(ClipboardFormatMetric::kPng);
+ std::vector<uint8_t> data = ReadPngInternal(buffer);
+ // On Windows, PNG and bitmap are separate formats. Read PNG if possible,
+ // otherwise fall back to reading as a bitmap.
+ if (data.empty()) {
+ SkBitmap bitmap = ReadImageInternal(buffer);
+ gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, /*discard_transparency=*/false,
+ &data);
+ }
+ std::move(callback).Run(data);
}
// |data_dst| is not used. It's only passed to be consistent with other
@@ -533,7 +558,7 @@ void ClipboardWin::ReadCustomData(ClipboardBuffer buffer,
return;
HANDLE hdata = ::GetClipboardData(
- ClipboardFormatType::GetWebCustomDataType().ToFormatEtc().cfFormat);
+ ClipboardFormatType::WebCustomDataType().ToFormatEtc().cfFormat);
if (!hdata)
return;
@@ -562,7 +587,7 @@ void ClipboardWin::ReadFilenames(ClipboardBuffer buffer,
// TODO(crbug.com/1178671): Refactor similar code in clipboard_utils_win:
// ClipboardUtil::GetFilenames() and reuse rather than duplicate.
HANDLE data = ::GetClipboardData(
- ClipboardFormatType::GetCFHDropType().ToFormatEtc().cfFormat);
+ ClipboardFormatType::CFHDropType().ToFormatEtc().cfFormat);
if (data) {
{
base::win::ScopedHGlobal<HDROP> hdrop(data);
@@ -583,7 +608,7 @@ void ClipboardWin::ReadFilenames(ClipboardBuffer buffer,
}
data = ::GetClipboardData(
- ClipboardFormatType::GetFilenameType().ToFormatEtc().cfFormat);
+ ClipboardFormatType::FilenameType().ToFormatEtc().cfFormat);
if (data) {
{
// filename using Unicode
@@ -597,7 +622,7 @@ void ClipboardWin::ReadFilenames(ClipboardBuffer buffer,
}
data = ::GetClipboardData(
- ClipboardFormatType::GetFilenameAType().ToFormatEtc().cfFormat);
+ ClipboardFormatType::FilenameAType().ToFormatEtc().cfFormat);
if (data) {
{
// filename using ASCII
@@ -627,8 +652,8 @@ void ClipboardWin::ReadBookmark(const DataTransferEndpoint* data_dst,
if (!clipboard.Acquire(GetClipboardWindow()))
return;
- HANDLE data = ::GetClipboardData(
- ClipboardFormatType::GetUrlType().ToFormatEtc().cfFormat);
+ HANDLE data =
+ ::GetClipboardData(ClipboardFormatType::UrlType().ToFormatEtc().cfFormat);
if (!data)
return;
@@ -666,37 +691,19 @@ void ClipboardWin::ReadData(const ClipboardFormatType& format,
// |data_src| is not used. It's only passed to be consistent with other
// platforms.
-void ClipboardWin::WritePortableRepresentations(
+void ClipboardWin::WritePortableAndPlatformRepresentations(
ClipboardBuffer buffer,
const ObjectMap& objects,
- std::unique_ptr<DataTransferEndpoint> data_src) {
- DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
-
- ScopedClipboard clipboard;
- if (!clipboard.Acquire(GetClipboardWindow()))
- return;
-
- ::EmptyClipboard();
-
- for (const auto& object : objects)
- DispatchPortableRepresentation(object.first, object.second);
-}
-
-// |data_src| is not used. It's only passed to be consistent with other
-// platforms.
-void ClipboardWin::WritePlatformRepresentations(
- ClipboardBuffer buffer,
std::vector<Clipboard::PlatformRepresentation> platform_representations,
std::unique_ptr<DataTransferEndpoint> data_src) {
- DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
-
ScopedClipboard clipboard;
if (!clipboard.Acquire(GetClipboardWindow()))
return;
-
::EmptyClipboard();
DispatchPlatformRepresentations(std::move(platform_representations));
+ for (const auto& object : objects)
+ DispatchPortableRepresentation(object.first, object.second);
}
void ClipboardWin::WriteText(const char* text_data, size_t text_len) {
@@ -704,7 +711,7 @@ void ClipboardWin::WriteText(const char* text_data, size_t text_len) {
base::UTF8ToUTF16(text_data, text_len, &text);
HGLOBAL glob = CreateGlobalData(text);
- WriteToClipboard(ClipboardFormatType::GetPlainTextType(), glob);
+ WriteToClipboard(ClipboardFormatType::PlainTextType(), glob);
}
void ClipboardWin::WriteHTML(const char* markup_data,
@@ -720,7 +727,7 @@ void ClipboardWin::WriteHTML(const char* markup_data,
std::string html_fragment = ClipboardUtil::HtmlToCFHtml(markup, url);
HGLOBAL glob = CreateGlobalData(html_fragment);
- WriteToClipboard(ClipboardFormatType::GetHtmlType(), glob);
+ WriteToClipboard(ClipboardFormatType::HtmlType(), glob);
}
void ClipboardWin::WriteSvg(const char* markup_data, size_t markup_len) {
@@ -728,18 +735,18 @@ void ClipboardWin::WriteSvg(const char* markup_data, size_t markup_len) {
base::UTF8ToUTF16(markup_data, markup_len, &markup);
HGLOBAL glob = CreateGlobalData(markup);
- WriteToClipboard(ClipboardFormatType::GetSvgType(), glob);
+ WriteToClipboard(ClipboardFormatType::SvgType(), glob);
}
void ClipboardWin::WriteRTF(const char* rtf_data, size_t data_len) {
- WriteData(ClipboardFormatType::GetRtfType(), rtf_data, data_len);
+ WriteData(ClipboardFormatType::RtfType(), rtf_data, data_len);
}
void ClipboardWin::WriteFilenames(std::vector<ui::FileInfo> filenames) {
STGMEDIUM storage = ClipboardUtil::CreateStorageForFileNames(filenames);
if (storage.tymed == TYMED_NULL)
return;
- WriteToClipboard(ClipboardFormatType::GetCFHDropType(), storage.hGlobal);
+ WriteToClipboard(ClipboardFormatType::CFHDropType(), storage.hGlobal);
}
void ClipboardWin::WriteBookmark(const char* title_data,
@@ -753,13 +760,13 @@ void ClipboardWin::WriteBookmark(const char* title_data,
std::u16string wide_bookmark = base::UTF8ToUTF16(bookmark);
HGLOBAL glob = CreateGlobalData(wide_bookmark);
- WriteToClipboard(ClipboardFormatType::GetUrlType(), glob);
+ WriteToClipboard(ClipboardFormatType::UrlType(), glob);
}
void ClipboardWin::WriteWebSmartPaste() {
DCHECK_NE(clipboard_owner_->hwnd(), nullptr);
::SetClipboardData(
- ClipboardFormatType::GetWebKitSmartPasteType().ToFormatEtc().cfFormat,
+ ClipboardFormatType::WebKitSmartPasteType().ToFormatEtc().cfFormat,
nullptr);
}
@@ -779,11 +786,11 @@ void ClipboardWin::WriteBitmap(const SkBitmap& bitmap) {
&png_encoded_bitmap)) {
HGLOBAL png_hglobal = skia::CreateHGlobalForByteArray(png_encoded_bitmap);
if (png_hglobal)
- WriteToClipboard(ClipboardFormatType::GetPngType(), png_hglobal);
+ WriteToClipboard(ClipboardFormatType::PngType(), png_hglobal);
}
HGLOBAL dibv5_hglobal = skia::CreateDIBV5ImageDataFromN32SkBitmap(bitmap);
if (dibv5_hglobal)
- WriteToClipboard(ClipboardFormatType::GetBitmapType(), dibv5_hglobal);
+ WriteToClipboard(ClipboardFormatType::BitmapType(), dibv5_hglobal);
}
void ClipboardWin::WriteData(const ClipboardFormatType& format,
@@ -799,6 +806,26 @@ void ClipboardWin::WriteData(const ClipboardFormatType& format,
WriteToClipboard(format, hdata);
}
+std::vector<uint8_t> ClipboardWin::ReadPngInternal(
+ ClipboardBuffer buffer) const {
+ DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
+
+ // Acquire the clipboard.
+ ScopedClipboard clipboard;
+ if (!clipboard.Acquire(GetClipboardWindow()))
+ return std::vector<uint8_t>();
+
+ HANDLE data =
+ ::GetClipboardData(ClipboardFormatType::PngType().ToFormatEtc().cfFormat);
+
+ if (!data)
+ return std::vector<uint8_t>();
+
+ std::string result(static_cast<const char*>(::GlobalLock(data)),
+ ::GlobalSize(data));
+ ::GlobalUnlock(data);
+ return std::vector<uint8_t>(result.begin(), result.end());
+}
SkBitmap ClipboardWin::ReadImageInternal(ClipboardBuffer buffer) const {
DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
@@ -816,6 +843,31 @@ SkBitmap ClipboardWin::ReadImageInternal(ClipboardBuffer buffer) const {
return SkBitmap();
int color_table_length = 0;
+ // Image is too large, and may cause an allocation failure.
+ // See https://crbug.com/1164680.
+ constexpr size_t kMaxImageSizeBytes = 1 << 27; // 128 MiB
+ size_t image_size_bytes;
+ // Estimate the number of bytes per pixel. For images with fewer than one byte
+ // pixel we will over-estimate the size. For compressed images we will
+ // over-estimate the size, but some overestimating of the storage size is okay
+ // and the calculation will be a good estimate of the decompressed size. The
+ // reported bug was for uncompressed 32-bit images where this code will give
+ // correct results.
+ size_t bytes_per_pixel = bitmap->bmiHeader.biBitCount / 8;
+ if (bytes_per_pixel == 0)
+ bytes_per_pixel = 1;
+ // Calculate the size of the bitmap. This is not an exact calculation but that
+ // doesn't matter for this purpose. If the calculation overflows then the
+ // image is too big. Return an empty image.
+ if (!base::CheckMul(
+ bitmap->bmiHeader.biWidth,
+ base::CheckMul(bitmap->bmiHeader.biHeight, bytes_per_pixel))
+ .AssignIfValid(&image_size_bytes))
+ return SkBitmap();
+ // If the image size is too big then return an empty image.
+ if (image_size_bytes > kMaxImageSizeBytes)
+ return SkBitmap();
+
// For more information on BITMAPINFOHEADER and biBitCount definition,
// see https://docs.microsoft.com/en-us/windows/win32/wmdm/-bitmapinfoheader
switch (bitmap->bmiHeader.biBitCount) {
diff --git a/chromium/ui/base/clipboard/clipboard_win.h b/chromium/ui/base/clipboard/clipboard_win.h
index 33b6abca99d..355190e6c1f 100644
--- a/chromium/ui/base/clipboard/clipboard_win.h
+++ b/chromium/ui/base/clipboard/clipboard_win.h
@@ -10,7 +10,6 @@
#include <memory>
-#include "base/macros.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/clipboard_format_type.h"
@@ -22,7 +21,14 @@ class MessageWindow;
namespace ui {
+// Documentation on the underlying Win32 API this ultimately abstracts is
+// available at
+// https://docs.microsoft.com/en-us/windows/win32/dataxchg/clipboard.
class ClipboardWin : public Clipboard {
+ public:
+ ClipboardWin(const ClipboardWin&) = delete;
+ ClipboardWin& operator=(const ClipboardWin&) = delete;
+
private:
friend class Clipboard;
@@ -32,7 +38,8 @@ class ClipboardWin : public Clipboard {
// Clipboard overrides:
void OnPreShutdown() override;
DataTransferEndpoint* GetSource(ClipboardBuffer buffer) const override;
- uint64_t GetSequenceNumber(ClipboardBuffer buffer) const override;
+ const ClipboardSequenceNumberToken& GetSequenceNumber(
+ ClipboardBuffer buffer) const override;
bool IsFormatAvailable(const ClipboardFormatType& format,
ClipboardBuffer buffer,
const DataTransferEndpoint* data_dst) const override;
@@ -80,12 +87,9 @@ class ClipboardWin : public Clipboard {
void ReadData(const ClipboardFormatType& format,
const DataTransferEndpoint* data_dst,
std::string* result) const override;
- void WritePortableRepresentations(
+ void WritePortableAndPlatformRepresentations(
ClipboardBuffer buffer,
const ObjectMap& objects,
- std::unique_ptr<DataTransferEndpoint> data_src) override;
- void WritePlatformRepresentations(
- ClipboardBuffer buffer,
std::vector<Clipboard::PlatformRepresentation> platform_representations,
std::unique_ptr<DataTransferEndpoint> data_src) override;
void WriteText(const char* text_data, size_t text_len) override;
@@ -105,6 +109,7 @@ class ClipboardWin : public Clipboard {
void WriteData(const ClipboardFormatType& format,
const char* data_data,
size_t data_len) override;
+ std::vector<uint8_t> ReadPngInternal(ClipboardBuffer buffer) const;
SkBitmap ReadImageInternal(ClipboardBuffer buffer) const;
// Safely write to system clipboard. Free |handle| on failure.
@@ -118,7 +123,11 @@ class ClipboardWin : public Clipboard {
// Mark this as mutable so const methods can still do lazy initialization.
mutable std::unique_ptr<base::win::MessageWindow> clipboard_owner_;
- DISALLOW_COPY_AND_ASSIGN(ClipboardWin);
+ // Mapping of OS-provided sequence number to a unique token.
+ mutable struct {
+ DWORD sequence_number;
+ ClipboardSequenceNumberToken token;
+ } clipboard_sequence_;
};
} // namespace ui
diff --git a/chromium/ui/base/clipboard/clipboard_x11.cc b/chromium/ui/base/clipboard/clipboard_x11.cc
index 2807d6e8ddc..304223c9d8e 100644
--- a/chromium/ui/base/clipboard/clipboard_x11.cc
+++ b/chromium/ui/base/clipboard/clipboard_x11.cc
@@ -8,6 +8,7 @@
#include <limits>
#include <memory>
#include <string>
+#include <vector>
#include "base/bind.h"
#include "base/containers/contains.h"
@@ -50,7 +51,8 @@ DataTransferEndpoint* ClipboardX11::GetSource(ClipboardBuffer buffer) const {
return it == data_src_.end() ? nullptr : it->second.get();
}
-uint64_t ClipboardX11::GetSequenceNumber(ClipboardBuffer buffer) const {
+const ClipboardSequenceNumberToken& ClipboardX11::GetSequenceNumber(
+ ClipboardBuffer buffer) const {
DCHECK(CalledOnValidThread());
return buffer == ClipboardBuffer::kCopyPaste ? clipboard_sequence_number_
: primary_sequence_number_;
@@ -88,10 +90,10 @@ void ClipboardX11::ReadAvailableTypes(
for (const auto& mime_type : available_types) {
// Special handling for chromium/x-web-custom-data. We must read the data
// and deserialize it to find the list of mime types to report.
- if (mime_type == ClipboardFormatType::GetWebCustomDataType().GetName()) {
+ if (mime_type == ClipboardFormatType::WebCustomDataType().GetName()) {
auto data(x_clipboard_helper_->Read(
buffer, x_clipboard_helper_->GetAtomsForFormat(
- ClipboardFormatType::GetWebCustomDataType())));
+ ClipboardFormatType::WebCustomDataType())));
if (data.IsValid())
ReadCustomDataTypes(data.GetData(), data.GetSize(), types);
} else {
@@ -162,8 +164,8 @@ void ClipboardX11::ReadHTML(ClipboardBuffer buffer,
*fragment_end = 0;
SelectionData data(x_clipboard_helper_->Read(
- buffer, x_clipboard_helper_->GetAtomsForFormat(
- ClipboardFormatType::GetHtmlType())));
+ buffer,
+ x_clipboard_helper_->GetAtomsForFormat(ClipboardFormatType::HtmlType())));
if (data.IsValid()) {
*markup = data.GetHtml();
@@ -182,8 +184,8 @@ void ClipboardX11::ReadSvg(ClipboardBuffer buffer,
RecordRead(ClipboardFormatMetric::kSvg);
SelectionData data(x_clipboard_helper_->Read(
- buffer, x_clipboard_helper_->GetAtomsForFormat(
- ClipboardFormatType::GetSvgType())));
+ buffer,
+ x_clipboard_helper_->GetAtomsForFormat(ClipboardFormatType::SvgType())));
if (data.IsValid()) {
std::string markup;
data.AssignTo(&markup);
@@ -200,8 +202,8 @@ void ClipboardX11::ReadRTF(ClipboardBuffer buffer,
RecordRead(ClipboardFormatMetric::kRtf);
SelectionData data(x_clipboard_helper_->Read(
- buffer, x_clipboard_helper_->GetAtomsForFormat(
- ClipboardFormatType::GetRtfType())));
+ buffer,
+ x_clipboard_helper_->GetAtomsForFormat(ClipboardFormatType::RtfType())));
if (data.IsValid())
data.AssignTo(result);
}
@@ -211,8 +213,9 @@ void ClipboardX11::ReadRTF(ClipboardBuffer buffer,
void ClipboardX11::ReadPng(ClipboardBuffer buffer,
const DataTransferEndpoint* data_dst,
ReadPngCallback callback) const {
- // TODO(crbug.com/1201018): Implement this.
- NOTIMPLEMENTED();
+ DCHECK(IsSupportedClipboardBuffer(buffer));
+ RecordRead(ClipboardFormatMetric::kPng);
+ std::move(callback).Run(ReadPngInternal(buffer));
}
// |data_dst| is not used. It's only passed to be consistent with other
@@ -222,7 +225,10 @@ void ClipboardX11::ReadImage(ClipboardBuffer buffer,
ReadImageCallback callback) const {
DCHECK(IsSupportedClipboardBuffer(buffer));
RecordRead(ClipboardFormatMetric::kImage);
- std::move(callback).Run(ReadImageInternal(buffer));
+ auto png_data = ReadPngInternal(buffer);
+ SkBitmap bitmap;
+ gfx::PNGCodec::Decode(png_data.data(), png_data.size(), &bitmap);
+ std::move(callback).Run(bitmap);
}
// |data_dst| is not used. It's only passed to be consistent with other
@@ -236,7 +242,7 @@ void ClipboardX11::ReadCustomData(ClipboardBuffer buffer,
SelectionData data(x_clipboard_helper_->Read(
buffer, x_clipboard_helper_->GetAtomsForFormat(
- ClipboardFormatType::GetWebCustomDataType())));
+ ClipboardFormatType::WebCustomDataType())));
if (data.IsValid())
ReadCustomDataForType(data.GetData(), data.GetSize(), type, result);
}
@@ -251,7 +257,7 @@ void ClipboardX11::ReadFilenames(ClipboardBuffer buffer,
SelectionData data(x_clipboard_helper_->Read(
buffer, x_clipboard_helper_->GetAtomsForFormat(
- ClipboardFormatType::GetFilenamesType())));
+ ClipboardFormatType::FilenamesType())));
std::string uri_list;
if (data.IsValid())
data.AssignTo(&uri_list);
@@ -289,20 +295,8 @@ bool ClipboardX11::IsSelectionBufferAvailable() const {
}
#endif // defined(USE_OZONE)
-// |data_src| is not used. It's only passed to be consistent with other
-// platforms.
-void ClipboardX11::WritePortableRepresentations(
- ClipboardBuffer buffer,
- const ObjectMap& objects,
- std::unique_ptr<DataTransferEndpoint> data_src) {
- DCHECK(CalledOnValidThread());
- DCHECK(IsSupportedClipboardBuffer(buffer));
-
- x_clipboard_helper_->CreateNewClipboardData();
- for (const auto& object : objects)
- DispatchPortableRepresentation(object.first, object.second);
- x_clipboard_helper_->TakeOwnershipOfSelection(buffer);
-
+void ClipboardX11::WritePortableTextRepresentation(ClipboardBuffer buffer,
+ const ObjectMap& objects) {
if (buffer == ClipboardBuffer::kCopyPaste) {
auto text_iter = objects.find(PortableFormat::kText);
if (text_iter != objects.end()) {
@@ -317,14 +311,13 @@ void ClipboardX11::WritePortableRepresentations(
ClipboardBuffer::kSelection);
}
}
-
- data_src_[buffer] = std::move(data_src);
}
// |data_src| is not used. It's only passed to be consistent with other
// platforms.
-void ClipboardX11::WritePlatformRepresentations(
+void ClipboardX11::WritePortableAndPlatformRepresentations(
ClipboardBuffer buffer,
+ const ObjectMap& objects,
std::vector<Clipboard::PlatformRepresentation> platform_representations,
std::unique_ptr<DataTransferEndpoint> data_src) {
DCHECK(CalledOnValidThread());
@@ -332,7 +325,12 @@ void ClipboardX11::WritePlatformRepresentations(
x_clipboard_helper_->CreateNewClipboardData();
DispatchPlatformRepresentations(std::move(platform_representations));
+ for (const auto& object : objects)
+ DispatchPortableRepresentation(object.first, object.second);
x_clipboard_helper_->TakeOwnershipOfSelection(buffer);
+
+ WritePortableTextRepresentation(buffer, objects);
+
data_src_[buffer] = std::move(data_src);
}
@@ -374,7 +372,7 @@ void ClipboardX11::WriteSvg(const char* markup_data, size_t markup_len) {
}
void ClipboardX11::WriteRTF(const char* rtf_data, size_t data_len) {
- WriteData(ClipboardFormatType::GetRtfType(), rtf_data, data_len);
+ WriteData(ClipboardFormatType::RtfType(), rtf_data, data_len);
}
void ClipboardX11::WriteFilenames(std::vector<ui::FileInfo> filenames) {
@@ -382,7 +380,7 @@ void ClipboardX11::WriteFilenames(std::vector<ui::FileInfo> filenames) {
scoped_refptr<base::RefCountedMemory> mem(
base::RefCountedString::TakeString(&uri_list));
x_clipboard_helper_->InsertMapping(
- ClipboardFormatType::GetFilenamesType().GetName(), mem);
+ ClipboardFormatType::FilenamesType().GetName(), mem);
}
void ClipboardX11::WriteBookmark(const char* title_data,
@@ -431,29 +429,30 @@ void ClipboardX11::WriteData(const ClipboardFormatType& format,
x_clipboard_helper_->InsertMapping(format.GetName(), mem);
}
-SkBitmap ClipboardX11::ReadImageInternal(ClipboardBuffer buffer) const {
+std::vector<uint8_t> ClipboardX11::ReadPngInternal(
+ ClipboardBuffer buffer) const {
DCHECK(CalledOnValidThread());
- // TODO(https://crbug.com/443355): Since now that ReadImage() is async,
- // refactor the code to keep a callback with the request, and invoke the
- // callback when the request is satisfied.
+ // TODO(https://crbug.com/443355): Since ReadPng() is async, refactor the code
+ // to keep a callback with the request, and invoke the callback when the
+ // request is satisfied.
SelectionData data(x_clipboard_helper_->Read(
- buffer, x_clipboard_helper_->GetAtomsForFormat(
- ClipboardFormatType::GetBitmapType())));
+ buffer,
+ x_clipboard_helper_->GetAtomsForFormat(ClipboardFormatType::PngType())));
+
if (data.IsValid()) {
- SkBitmap bitmap;
- if (gfx::PNGCodec::Decode(data.GetData(), data.GetSize(), &bitmap))
- return SkBitmap(bitmap);
+ return std::vector<uint8_t>(data.GetData(),
+ data.GetData() + data.GetSize());
}
- return SkBitmap();
+ return std::vector<uint8_t>();
}
void ClipboardX11::OnSelectionChanged(ClipboardBuffer buffer) {
if (buffer == ClipboardBuffer::kCopyPaste)
- clipboard_sequence_number_++;
+ clipboard_sequence_number_ = ClipboardSequenceNumberToken();
else
- primary_sequence_number_++;
+ primary_sequence_number_ = ClipboardSequenceNumberToken();
ClipboardMonitor::GetInstance()->NotifyClipboardDataChanged();
}
diff --git a/chromium/ui/base/clipboard/clipboard_x11.h b/chromium/ui/base/clipboard/clipboard_x11.h
index 88a5ed96273..be7eb96c88e 100644
--- a/chromium/ui/base/clipboard/clipboard_x11.h
+++ b/chromium/ui/base/clipboard/clipboard_x11.h
@@ -8,7 +8,6 @@
#include <cstdint>
#include <memory>
-#include "base/macros.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/clipboard_buffer.h"
@@ -17,6 +16,10 @@ namespace ui {
class XClipboardHelper;
class ClipboardX11 : public Clipboard {
+ public:
+ ClipboardX11(const ClipboardX11&) = delete;
+ ClipboardX11& operator=(const ClipboardX11&) = delete;
+
private:
friend class Clipboard;
@@ -26,7 +29,8 @@ class ClipboardX11 : public Clipboard {
// Clipboard overrides:
void OnPreShutdown() override;
DataTransferEndpoint* GetSource(ClipboardBuffer buffer) const override;
- uint64_t GetSequenceNumber(ClipboardBuffer buffer) const override;
+ const ClipboardSequenceNumberToken& GetSequenceNumber(
+ ClipboardBuffer buffer) const override;
bool IsFormatAvailable(const ClipboardFormatType& format,
ClipboardBuffer buffer,
const DataTransferEndpoint* data_dst) const override;
@@ -77,12 +81,11 @@ class ClipboardX11 : public Clipboard {
#if defined(USE_OZONE)
bool IsSelectionBufferAvailable() const override;
#endif // defined(USE_OZONE)
- void WritePortableRepresentations(
+ void WritePortableTextRepresentation(ClipboardBuffer buffer,
+ const ObjectMap& objects);
+ void WritePortableAndPlatformRepresentations(
ClipboardBuffer buffer,
const ObjectMap& objects,
- std::unique_ptr<DataTransferEndpoint> data_src) override;
- void WritePlatformRepresentations(
- ClipboardBuffer buffer,
std::vector<Clipboard::PlatformRepresentation> platform_representations,
std::unique_ptr<DataTransferEndpoint> data_src) override;
void WriteText(const char* text_data, size_t text_len) override;
@@ -103,18 +106,16 @@ class ClipboardX11 : public Clipboard {
const char* data_data,
size_t data_len) override;
- SkBitmap ReadImageInternal(ClipboardBuffer buffer) const;
+ std::vector<uint8_t> ReadPngInternal(ClipboardBuffer buffer) const;
void OnSelectionChanged(ClipboardBuffer buffer);
std::unique_ptr<XClipboardHelper> x_clipboard_helper_;
- uint64_t clipboard_sequence_number_ = 0;
- uint64_t primary_sequence_number_ = 0;
+ ClipboardSequenceNumberToken clipboard_sequence_number_;
+ ClipboardSequenceNumberToken primary_sequence_number_;
base::flat_map<ClipboardBuffer, std::unique_ptr<DataTransferEndpoint>>
data_src_;
-
- DISALLOW_COPY_AND_ASSIGN(ClipboardX11);
};
} // namespace ui
diff --git a/chromium/ui/base/clipboard/scoped_clipboard_writer.cc b/chromium/ui/base/clipboard/scoped_clipboard_writer.cc
index 4e2394e4116..153f169d2cd 100644
--- a/chromium/ui/base/clipboard/scoped_clipboard_writer.cc
+++ b/chromium/ui/base/clipboard/scoped_clipboard_writer.cc
@@ -6,8 +6,10 @@
#include <memory>
#include <utility>
+#include "base/json/json_writer.h"
#include "base/pickle.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
#include "net/base/escape.h"
#include "ui/base/clipboard/clipboard_format_type.h"
#include "ui/base/clipboard/clipboard_metrics.h"
@@ -24,16 +26,24 @@ ScopedClipboardWriter::ScopedClipboardWriter(
ScopedClipboardWriter::~ScopedClipboardWriter() {
static constexpr size_t kMaxRepresentations = 1 << 12;
- DCHECK(objects_.empty() || platform_representations_.empty())
- << "Portable and Platform representations should not be written on the "
- "same write.";
DCHECK(platform_representations_.size() < kMaxRepresentations);
- if (!objects_.empty()) {
- Clipboard::GetForCurrentThread()->WritePortableRepresentations(
- buffer_, objects_, std::move(data_src_));
- } else if (!platform_representations_.empty()) {
- Clipboard::GetForCurrentThread()->WritePlatformRepresentations(
- buffer_, std::move(platform_representations_), std::move(data_src_));
+ // If the metadata format type is not empty then create a JSON payload and
+ // write to the clipboard.
+ if (!registered_formats_.empty()) {
+ std::string custom_format_json;
+ base::Value registered_formats_value(base::Value::Type::DICTIONARY);
+ for (const auto& item : registered_formats_)
+ registered_formats_value.SetStringKey(item.first, item.second);
+ base::JSONWriter::Write(registered_formats_value, &custom_format_json);
+ Clipboard::ObjectMapParams parameters;
+ parameters.push_back(Clipboard::ObjectMapParam(custom_format_json.begin(),
+ custom_format_json.end()));
+ objects_[Clipboard::PortableFormat::kWebCustomFormatMap] = parameters;
+ }
+ if (!objects_.empty() || !platform_representations_.empty()) {
+ Clipboard::GetForCurrentThread()->WritePortableAndPlatformRepresentations(
+ buffer_, objects_, std::move(platform_representations_),
+ std::move(data_src_));
}
if (confidential_)
@@ -176,15 +186,39 @@ void ScopedClipboardWriter::WritePickledData(
void ScopedClipboardWriter::WriteData(const std::u16string& format,
mojo_base::BigBuffer data) {
RecordWrite(ClipboardFormatMetric::kData);
- platform_representations_.push_back(
- {base::UTF16ToUTF8(format), std::move(data)});
+ // Windows / X11 clipboards enter an unrecoverable state after registering
+ // some amount of unique formats, and there's no way to un-register these
+ // formats. For these clipboards, use a conservative limit to avoid
+ // registering too many formats, as:
+ // (1) Other native applications may also register clipboard formats.
+ // (2) Malicious sites can write more than the hard limit defined on
+ // Windows(16k). (3) Chrome also registers other clipboard formats.
+ //
+ // There will be a custom format map which contains a JSON payload that will
+ // have a mapping of custom format MIME type to web custom format.
+ // There can only be 100 custom format per write and it will be
+ // registered when the web authors request for a custom format.
+ static constexpr int kMaxRegisteredFormats = 100;
+ if (counter_ >= kMaxRegisteredFormats)
+ return;
+ std::string format_in_ascii = base::UTF16ToASCII(format);
+ if (registered_formats_.find(format_in_ascii) == registered_formats_.end()) {
+ std::string web_custom_format_string =
+ ClipboardFormatType::WebCustomFormatName(counter_);
+ registered_formats_[format_in_ascii] = web_custom_format_string;
+ counter_++;
+ platform_representations_.push_back(
+ {web_custom_format_string, std::move(data)});
+ }
}
void ScopedClipboardWriter::Reset() {
objects_.clear();
platform_representations_.clear();
+ registered_formats_.clear();
bitmap_.reset();
confidential_ = false;
+ counter_ = 0;
}
} // namespace ui
diff --git a/chromium/ui/base/clipboard/scoped_clipboard_writer.h b/chromium/ui/base/clipboard/scoped_clipboard_writer.h
index 4d5122026dd..879acd4f6f0 100644
--- a/chromium/ui/base/clipboard/scoped_clipboard_writer.h
+++ b/chromium/ui/base/clipboard/scoped_clipboard_writer.h
@@ -8,7 +8,7 @@
#include <string>
#include "base/component_export.h"
-#include "base/macros.h"
+#include "base/containers/flat_map.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/data_transfer_policy/data_transfer_endpoint.h"
@@ -36,7 +36,8 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ScopedClipboardWriter {
explicit ScopedClipboardWriter(
ClipboardBuffer buffer,
std::unique_ptr<DataTransferEndpoint> src = nullptr);
-
+ ScopedClipboardWriter(const ScopedClipboardWriter&) = delete;
+ ScopedClipboardWriter& operator=(const ScopedClipboardWriter&) = delete;
~ScopedClipboardWriter();
// Converts |text| to UTF-8 and adds it to the clipboard.
@@ -76,6 +77,7 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ScopedClipboardWriter {
// Data is written to the system clipboard in the same order as WriteData
// calls are received.
+ // This is only used to write custom format data.
void WriteData(const std::u16string& format, mojo_base::BigBuffer data);
void WriteImage(const SkBitmap& bitmap);
@@ -93,6 +95,9 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ScopedClipboardWriter {
Clipboard::ObjectMap objects_;
std::vector<Clipboard::PlatformRepresentation> platform_representations_;
+ // Keeps track of the unique custom formats registered in the clipboard.
+ base::flat_map<std::string, std::string> registered_formats_;
+ int counter_ = 0;
// The type is set at construction, and can be changed before committing.
const ClipboardBuffer buffer_;
@@ -105,8 +110,6 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ScopedClipboardWriter {
// not set, or the source of the data can't be represented by
// DataTransferEndpoint.
std::unique_ptr<DataTransferEndpoint> data_src_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedClipboardWriter);
};
} // namespace ui