Browse Source

fix: clipboard.writeBuffer raw format access (#31116)

* fix: clipboard.writeBuffer raw format access

* test: clipboard.writeBuffer raw format access

* test: clipboard win32 test skip

* fixup spec

* cleanup patch

Co-authored-by: John Kleinschmidt <[email protected]>
henrit 3 years ago
parent
commit
3c33d70294

+ 1 - 0
patches/chromium/.patches

@@ -106,6 +106,7 @@ feat_expose_raw_response_headers_from_urlloader.patch
 chore_do_not_use_chrome_windows_in_cryptotoken_webrequestsender.patch
 process_singleton.patch
 fix_expose_decrementcapturercount_in_web_contents_impl.patch
+add_ui_scopedcliboardwriter_writeunsaferawdata.patch
 feat_add_data_parameter_to_processsingleton.patch
 mas_gate_private_enterprise_APIs
 load_v8_snapshot_in_browser_process.patch

+ 45 - 0
patches/chromium/add_ui_scopedcliboardwriter_writeunsaferawdata.patch

@@ -0,0 +1,45 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Henri Torgemane <[email protected]>
+Date: Thu, 23 Sep 2021 21:30:33 -0500
+Subject: add ui::ScopedCliboardWriter::WriteUnsafeRawData
+
+This restores some ability to write to the clipboard using raw formats, which
+was removed as part of the Raw Clipboard API scrubbing.
+https://bugs.chromium.org/p/chromium/issues/detail?id=1217643
+
+diff --git a/ui/base/clipboard/scoped_clipboard_writer.cc b/ui/base/clipboard/scoped_clipboard_writer.cc
+index 153f169d2cdef6f8a726c188283a5bc1b7395fa3..3a5d9ab8dafacafb1025e1cb8c157e8a82078424 100644
+--- a/ui/base/clipboard/scoped_clipboard_writer.cc
++++ b/ui/base/clipboard/scoped_clipboard_writer.cc
+@@ -212,6 +212,16 @@ void ScopedClipboardWriter::WriteData(const std::u16string& format,
+   }
+ }
+ 
++void ScopedClipboardWriter::WriteUnsafeRawData(const std::u16string& format,
++                                               mojo_base::BigBuffer data) {
++  static constexpr int kMaxRegisteredFormats = 100;
++  if (counter_ >= kMaxRegisteredFormats)
++    return;
++  counter_++;
++  platform_representations_.push_back(
++      {base::UTF16ToUTF8(format), std::move(data)});
++}
++
+ void ScopedClipboardWriter::Reset() {
+   objects_.clear();
+   platform_representations_.clear();
+diff --git a/ui/base/clipboard/scoped_clipboard_writer.h b/ui/base/clipboard/scoped_clipboard_writer.h
+index 879acd4f6f0101a6da3af58d78eeda877ea41a4a..4d4149b6aa34c7073804994cb1c03368830c736d 100644
+--- a/ui/base/clipboard/scoped_clipboard_writer.h
++++ b/ui/base/clipboard/scoped_clipboard_writer.h
+@@ -80,6 +80,10 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ScopedClipboardWriter {
+   // This is only used to write custom format data.
+   void WriteData(const std::u16string& format, mojo_base::BigBuffer data);
+ 
++  // write raw (non-pickled) data to the clipboard
++  void WriteUnsafeRawData(const std::u16string& format,
++                          mojo_base::BigBuffer data);
++
+   void WriteImage(const SkBitmap& bitmap);
+ 
+   // Mark the data to be written as confidential.

+ 19 - 3
shell/common/api/electron_api_clipboard.cc

@@ -51,7 +51,23 @@ bool Clipboard::Has(const std::string& format_string,
 
 std::string Clipboard::Read(const std::string& format_string) {
   ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
-
+  // Prefer raw platform format names
+  ui::ClipboardFormatType rawFormat(
+      ui::ClipboardFormatType::CustomPlatformType(format_string));
+  bool rawFormatAvailable = clipboard->IsFormatAvailable(
+      rawFormat, ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr);
+#if defined(OS_LINUX)
+  if (!rawFormatAvailable) {
+    rawFormatAvailable = clipboard->IsFormatAvailable(
+        rawFormat, ui::ClipboardBuffer::kSelection, /* data_dst = */ nullptr);
+  }
+#endif
+  if (rawFormatAvailable) {
+    std::string data;
+    clipboard->ReadData(rawFormat, /* data_dst = */ nullptr, &data);
+    return data;
+  }
+  // Otherwise, resolve custom format names
   std::map<std::string, std::string> custom_format_names;
   custom_format_names =
       clipboard->ExtractCustomPlatformNames(ui::ClipboardBuffer::kCopyPaste,
@@ -97,8 +113,8 @@ void Clipboard::WriteBuffer(const std::string& format,
   base::span<const uint8_t> payload_span(
       reinterpret_cast<const uint8_t*>(node::Buffer::Data(buffer)),
       node::Buffer::Length(buffer));
-  writer.WriteData(base::UTF8ToUTF16(format),
-                   mojo_base::BigBuffer(payload_span));
+  writer.WriteUnsafeRawData(base::UTF8ToUTF16(format),
+                            mojo_base::BigBuffer(payload_span));
 }
 
 void Clipboard::Write(const gin_helper::Dictionary& data,

+ 11 - 0
spec/api-clipboard-spec.js

@@ -129,5 +129,16 @@ ifdescribe(process.platform !== 'win32' || process.arch !== 'arm64')('clipboard
         clipboard.writeBuffer('public/utf8-plain-text', 'hello');
       }).to.throw(/buffer must be a node Buffer/);
     });
+
+    ifit(process.platform !== 'win32')('writes a Buffer using a raw format that is used by native apps', function () {
+      const message = 'Hello from Electron!';
+      const buffer = Buffer.from(message);
+      let rawFormat = 'text/plain';
+      if (process.platform === 'darwin') {
+        rawFormat = 'public.utf8-plain-text';
+      }
+      clipboard.writeBuffer(rawFormat, buffer);
+      expect(clipboard.readText()).to.equal(message);
+    });
   });
 });