Avi Drissman | 4e1b7bc3 | 2022-09-15 14:03:50 | [diff] [blame] | 1 | // Copyright 2012 The Chromium Authors |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 5 | #include "content/browser/renderer_host/clipboard_host_impl.h" |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 6 | |
Peter Kasting | 1557e5f | 2025-01-28 01:14:08 | [diff] [blame] | 7 | #include <algorithm> |
Aya ElAttar | fd04e3a | 2020-08-05 17:17:37 | [diff] [blame] | 8 | #include <memory> |
Roger Tawa | c617026 | 2022-10-28 23:48:52 | [diff] [blame] | 9 | #include <set> |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 10 | #include <utility> |
| 11 | |
Luca Accorsi | b52ca00 | 2023-12-01 08:54:26 | [diff] [blame] | 12 | #include "base/files/file_path.h" |
Avi Drissman | adac2199 | 2023-01-11 23:46:39 | [diff] [blame] | 13 | #include "base/functional/bind.h" |
Daniel Cheng | 6300516f | 2018-10-09 02:13:24 | [diff] [blame] | 14 | #include "base/location.h" |
Daniel Cheng | 6f7e1c2 | 2021-02-02 05:47:54 | [diff] [blame] | 15 | #include "base/memory/ptr_util.h" |
Keishi Hattori | 504ae46 | 2023-03-29 05:10:06 | [diff] [blame] | 16 | #include "base/memory/raw_ptr_exclusion.h" |
Austin Sullivan | fc87089 | 2021-04-29 18:40:11 | [diff] [blame] | 17 | #include "base/notreached.h" |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 18 | #include "base/pickle.h" |
Roger Tawa | c617026 | 2022-10-28 23:48:52 | [diff] [blame] | 19 | #include "base/strings/string_util.h" |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 20 | #include "base/strings/utf_string_conversions.h" |
Patrick Monette | 643cdf6 | 2021-10-15 19:13:42 | [diff] [blame] | 21 | #include "base/task/sequenced_task_runner.h" |
Dominique Fauteux-Chapleau | c95ca12 | 2023-11-02 19:34:33 | [diff] [blame] | 22 | #include "base/types/optional_util.h" |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 23 | #include "build/build_config.h" |
Joel Hockey | 4c0cb8c | 2021-02-22 02:59:59 | [diff] [blame] | 24 | #include "content/browser/file_system/browser_file_system_helper.h" |
| 25 | #include "content/browser/file_system_access/file_system_access_manager_impl.h" |
Darwin Huang | 6195d04 | 2021-02-12 22:36:00 | [diff] [blame] | 26 | #include "content/browser/permissions/permission_controller_impl.h" |
Joel Hockey | d75d506 | 2021-02-23 19:53:25 | [diff] [blame] | 27 | #include "content/browser/renderer_host/data_transfer_util.h" |
Aya ElAttar | f0ebeecf07 | 2021-03-05 10:52:15 | [diff] [blame] | 28 | #include "content/browser/renderer_host/render_frame_host_delegate.h" |
Joel Hockey | 4c0cb8c | 2021-02-22 02:59:59 | [diff] [blame] | 29 | #include "content/browser/storage_partition_impl.h" |
Sergey Poromov | 0bd4819 | 2021-07-16 18:45:59 | [diff] [blame] | 30 | #include "content/public/browser/browser_context.h" |
Will Harris | cd57b83 | 2023-01-05 20:03:10 | [diff] [blame] | 31 | #include "content/public/browser/child_process_host.h" |
Dominique Fauteux-Chapleau | 61a5359 | 2025-01-17 15:21:34 | [diff] [blame] | 32 | #include "content/public/browser/clipboard_types.h" |
Roger Tawa | 1e1812f8 | 2020-01-16 15:23:30 | [diff] [blame] | 33 | #include "content/public/browser/render_frame_host.h" |
| 34 | #include "content/public/browser/render_process_host.h" |
Darwin Huang | 6195d04 | 2021-02-12 22:36:00 | [diff] [blame] | 35 | #include "content/public/common/content_client.h" |
Joel Hockey | 4c0cb8c | 2021-02-22 02:59:59 | [diff] [blame] | 36 | #include "content/public/common/drop_data.h" |
Daniel Cheng | 6f7e1c2 | 2021-02-02 05:47:54 | [diff] [blame] | 37 | #include "mojo/public/cpp/bindings/self_owned_receiver.h" |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 38 | #include "mojo/public/cpp/system/platform_handle.h" |
danakj | bdf1e0a | 2020-11-10 18:27:47 | [diff] [blame] | 39 | #include "skia/ext/skia_utils_base.h" |
Joel Hockey | 4c0cb8c | 2021-02-22 02:59:59 | [diff] [blame] | 40 | #include "third_party/blink/public/mojom/clipboard/clipboard.mojom.h" |
Sharon Yang | 2abe198 | 2021-10-01 15:56:34 | [diff] [blame] | 41 | #include "third_party/blink/public/mojom/drag/drag.mojom-forward.h" |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 42 | #include "third_party/skia/include/core/SkBitmap.h" |
| 43 | #include "ui/base/clipboard/clipboard.h" |
Maksim Sisov | a33072d2 | 2019-01-24 15:44:25 | [diff] [blame] | 44 | #include "ui/base/clipboard/clipboard_constants.h" |
Roger Tawa | 03ffdbd | 2020-01-16 18:12:54 | [diff] [blame] | 45 | #include "ui/base/clipboard/clipboard_format_type.h" |
Dominique Fauteux-Chapleau | ed894b7 | 2024-03-19 12:19:41 | [diff] [blame] | 46 | #include "ui/base/clipboard/clipboard_monitor.h" |
| 47 | #include "ui/base/clipboard/clipboard_observer.h" |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 48 | #include "ui/base/clipboard/custom_data_helper.h" |
Joel Hockey | 4c0cb8c | 2021-02-22 02:59:59 | [diff] [blame] | 49 | #include "ui/base/clipboard/file_info.h" |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 50 | #include "ui/base/clipboard/scoped_clipboard_writer.h" |
Aya ElAttar | 281086a | 2020-10-29 12:09:22 | [diff] [blame] | 51 | #include "ui/base/data_transfer_policy/data_transfer_endpoint.h" |
Aya ElAttar | 84e6ef3 | 2021-03-02 16:29:19 | [diff] [blame] | 52 | #include "ui/base/data_transfer_policy/data_transfer_policy_controller.h" |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 53 | #include "url/gurl.h" |
| 54 | |
Georg Neis | 35ff854b | 2024-12-17 02:02:08 | [diff] [blame] | 55 | #if BUILDFLAG(IS_CHROMEOS) |
Joel Hockey | 9fe6d6b8 | 2023-06-28 23:11:13 | [diff] [blame] | 56 | #include "content/public/common/url_constants.h" |
Georg Neis | 35ff854b | 2024-12-17 02:02:08 | [diff] [blame] | 57 | #endif // BUILDFLAG(IS_CHROMEOS) |
Joel Hockey | 9fe6d6b8 | 2023-06-28 23:11:13 | [diff] [blame] | 58 | |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 59 | namespace content { |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 60 | |
Roger Tawa | c774694b | 2023-03-16 20:44:39 | [diff] [blame] | 61 | namespace { |
| 62 | |
Nancy Xiao | 200f55b | 2023-05-03 13:24:47 | [diff] [blame] | 63 | std::u16string ExtractText(ui::ClipboardBuffer clipboard_buffer, |
| 64 | std::unique_ptr<ui::DataTransferEndpoint> data_dst) { |
| 65 | ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread(); |
| 66 | std::u16string result; |
| 67 | if (clipboard->IsFormatAvailable(ui::ClipboardFormatType::PlainTextType(), |
| 68 | clipboard_buffer, data_dst.get())) { |
| 69 | clipboard->ReadText(clipboard_buffer, data_dst.get(), &result); |
| 70 | } else { |
| 71 | #if BUILDFLAG(IS_WIN) |
| 72 | if (clipboard->IsFormatAvailable(ui::ClipboardFormatType::PlainTextAType(), |
| 73 | clipboard_buffer, data_dst.get())) { |
| 74 | std::string ascii; |
| 75 | clipboard->ReadAsciiText(clipboard_buffer, data_dst.get(), &ascii); |
| 76 | result = base::ASCIIToUTF16(ascii); |
| 77 | } |
| 78 | #endif |
| 79 | } |
| 80 | return result; |
| 81 | } |
| 82 | |
Roger Tawa | c774694b | 2023-03-16 20:44:39 | [diff] [blame] | 83 | } // namespace |
| 84 | |
Dominique Fauteux-Chapleau | c174eaa | 2024-02-12 19:29:24 | [diff] [blame] | 85 | ClipboardEndpoint GetSourceClipboardEndpoint( |
Dominique Fauteux-Chapleau | 61a5359 | 2025-01-17 15:21:34 | [diff] [blame] | 86 | const ui::DataTransferEndpoint* data_dst, |
Dominique Fauteux-Chapleau | c174eaa | 2024-02-12 19:29:24 | [diff] [blame] | 87 | ui::ClipboardBuffer clipboard_buffer) { |
Dominique Fauteux-Chapleau | 61a5359 | 2025-01-17 15:21:34 | [diff] [blame] | 88 | auto* clipboard = ui::Clipboard::GetForCurrentThread(); |
| 89 | std::string pickled_rfh_token; |
| 90 | clipboard->ReadData(SourceRFHTokenType(), data_dst, &pickled_rfh_token); |
Dominique Fauteux-Chapleau | c174eaa | 2024-02-12 19:29:24 | [diff] [blame] | 91 | |
Dominique Fauteux-Chapleau | 61a5359 | 2025-01-17 15:21:34 | [diff] [blame] | 92 | auto rfh_token = GlobalRenderFrameHostToken::FromPickle( |
| 93 | base::Pickle::WithData(base::as_byte_span(pickled_rfh_token))); |
| 94 | |
| 95 | RenderFrameHost* rfh = nullptr; |
| 96 | if (rfh_token) { |
| 97 | rfh = RenderFrameHost::FromFrameToken(*rfh_token); |
| 98 | } |
| 99 | |
| 100 | if (!rfh) { |
Dominique Fauteux-Chapleau | c174eaa | 2024-02-12 19:29:24 | [diff] [blame] | 101 | // Fall back to the clipboard source if there is no `seqno` match or RFH, as |
| 102 | // `ui::DataTransferEndpoint` can be populated differently based on |
| 103 | // platform. |
Dominique Fauteux-Chapleau | 61a5359 | 2025-01-17 15:21:34 | [diff] [blame] | 104 | return ClipboardEndpoint(clipboard->GetSource(clipboard_buffer)); |
Dominique Fauteux-Chapleau | c174eaa | 2024-02-12 19:29:24 | [diff] [blame] | 105 | } |
| 106 | |
| 107 | std::optional<ui::DataTransferEndpoint> source_dte; |
Dominique Fauteux-Chapleau | 61a5359 | 2025-01-17 15:21:34 | [diff] [blame] | 108 | auto clipboard_source_dte = clipboard->GetSource(clipboard_buffer); |
Dominique Fauteux-Chapleau | c174eaa | 2024-02-12 19:29:24 | [diff] [blame] | 109 | if (clipboard_source_dte) { |
| 110 | if (clipboard_source_dte->IsUrlType()) { |
| 111 | source_dte = std::make_optional<ui::DataTransferEndpoint>( |
| 112 | *clipboard_source_dte->GetURL(), |
Dominique Fauteux-Chapleau | 5e305e8 | 2024-06-21 00:02:03 | [diff] [blame] | 113 | ui::DataTransferEndpointOptions{ |
| 114 | .off_the_record = rfh->GetBrowserContext()->IsOffTheRecord()}); |
Dominique Fauteux-Chapleau | c174eaa | 2024-02-12 19:29:24 | [diff] [blame] | 115 | } else { |
| 116 | source_dte = std::move(clipboard_source_dte); |
| 117 | } |
| 118 | } |
| 119 | |
| 120 | return ClipboardEndpoint( |
| 121 | std::move(source_dte), |
| 122 | base::BindRepeating( |
Dominique Fauteux-Chapleau | 61a5359 | 2025-01-17 15:21:34 | [diff] [blame] | 123 | [](GlobalRenderFrameHostToken rfh_token) -> BrowserContext* { |
| 124 | auto* rfh = RenderFrameHost::FromFrameToken(rfh_token); |
Dominique Fauteux-Chapleau | c174eaa | 2024-02-12 19:29:24 | [diff] [blame] | 125 | if (!rfh) { |
| 126 | return nullptr; |
| 127 | } |
| 128 | return rfh->GetBrowserContext(); |
| 129 | }, |
Dominique Fauteux-Chapleau | 61a5359 | 2025-01-17 15:21:34 | [diff] [blame] | 130 | rfh->GetGlobalFrameToken()), |
Dominique Fauteux-Chapleau | c174eaa | 2024-02-12 19:29:24 | [diff] [blame] | 131 | *rfh); |
| 132 | } |
| 133 | |
Alexander Timin | e3383d0 | 2021-06-24 19:57:59 | [diff] [blame] | 134 | ClipboardHostImpl::ClipboardHostImpl( |
danakj | c70aec1f | 2022-07-07 15:48:19 | [diff] [blame] | 135 | RenderFrameHost& render_frame_host, |
Alexander Timin | e3383d0 | 2021-06-24 19:57:59 | [diff] [blame] | 136 | mojo::PendingReceiver<blink::mojom::ClipboardHost> receiver) |
Daniel Cheng | 9fb887ff | 2021-10-01 20:27:38 | [diff] [blame] | 137 | : DocumentService(render_frame_host, std::move(receiver)) { |
Dominique Fauteux-Chapleau | 61a5359 | 2025-01-17 15:21:34 | [diff] [blame] | 138 | ResetClipboardWriter(); |
Roger Tawa | 1e1812f8 | 2020-01-16 15:23:30 | [diff] [blame] | 139 | } |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 140 | |
Julie Jeongeun Kim | 44b804b2 | 2019-08-15 06:14:55 | [diff] [blame] | 141 | void ClipboardHostImpl::Create( |
Roger Tawa | 1e1812f8 | 2020-01-16 15:23:30 | [diff] [blame] | 142 | RenderFrameHost* render_frame_host, |
Julie Jeongeun Kim | 44b804b2 | 2019-08-15 06:14:55 | [diff] [blame] | 143 | mojo::PendingReceiver<blink::mojom::ClipboardHost> receiver) { |
danakj | c70aec1f | 2022-07-07 15:48:19 | [diff] [blame] | 144 | CHECK(render_frame_host); |
Alexander Timin | e3383d0 | 2021-06-24 19:57:59 | [diff] [blame] | 145 | // The object is bound to the lifetime of |render_frame_host| and the mojo |
Daniel Cheng | 9fb887ff | 2021-10-01 20:27:38 | [diff] [blame] | 146 | // connection. See DocumentService for details. |
danakj | c70aec1f | 2022-07-07 15:48:19 | [diff] [blame] | 147 | new ClipboardHostImpl(*render_frame_host, std::move(receiver)); |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 148 | } |
| 149 | |
| 150 | ClipboardHostImpl::~ClipboardHostImpl() { |
| 151 | clipboard_writer_->Reset(); |
Rohan Raja | 183dfd9 | 2025-04-22 21:41:09 | [diff] [blame] | 152 | if (listening_to_clipboard_) { |
| 153 | ui::ClipboardMonitor::GetInstance()->RemoveObserver(this); |
| 154 | listening_to_clipboard_ = false; |
| 155 | } |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 156 | } |
| 157 | |
Darwin Huang | 5c6614c5 | 2019-08-21 01:20:10 | [diff] [blame] | 158 | void ClipboardHostImpl::GetSequenceNumber(ui::ClipboardBuffer clipboard_buffer, |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 159 | GetSequenceNumberCallback callback) { |
Pavol Marko | c73be302 | 2021-07-05 15:41:20 | [diff] [blame] | 160 | std::move(callback).Run( |
| 161 | ui::Clipboard::GetForCurrentThread()->GetSequenceNumber( |
| 162 | clipboard_buffer)); |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 163 | } |
| 164 | |
| 165 | void ClipboardHostImpl::ReadAvailableTypes( |
Darwin Huang | 5c6614c5 | 2019-08-21 01:20:10 | [diff] [blame] | 166 | ui::ClipboardBuffer clipboard_buffer, |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 167 | ReadAvailableTypesCallback callback) { |
Jan Wilken Dörrie | aace0cfef | 2021-03-11 22:01:58 | [diff] [blame] | 168 | std::vector<std::u16string> types; |
Joel Hockey | c69b644 | 2021-09-06 09:27:33 | [diff] [blame] | 169 | auto* clipboard = ui::Clipboard::GetForCurrentThread(); |
| 170 | auto data_endpoint = CreateDataEndpoint(); |
| 171 | |
Haihan Chen | 715e675 | 2025-06-18 19:30:25 | [diff] [blame] | 172 | // If an enterprise Data Controls rule modified the clipboard, get the last |
| 173 | // replaced clipboard types instead. |
| 174 | if (auto policy_types = |
| 175 | static_cast<RenderFrameHostImpl&>(render_frame_host()) |
| 176 | .GetClipboardTypesIfPolicyApplied( |
| 177 | clipboard->GetSequenceNumber(clipboard_buffer))) { |
| 178 | types = std::move(*policy_types); |
| 179 | } else { |
| 180 | // ReadAvailableTypes() returns 'text/uri-list' if either files are |
| 181 | // provided, or if it was set as a custom web type. If it is set because |
| 182 | // files are available, do not include other types such as text/plain which |
| 183 | // contain the full path on some platforms (http://crbug.com/1214108). But |
| 184 | // do not exclude other types when it is set as a custom web type |
| 185 | // (http://crbug.com/1241671). |
| 186 | bool file_type_only = |
| 187 | clipboard->IsFormatAvailable(ui::ClipboardFormatType::FilenamesType(), |
| 188 | clipboard_buffer, data_endpoint.get()); |
Joel Hockey | 9fe6d6b8 | 2023-06-28 23:11:13 | [diff] [blame] | 189 | |
Georg Neis | 35ff854b | 2024-12-17 02:02:08 | [diff] [blame] | 190 | #if BUILDFLAG(IS_CHROMEOS) |
Haihan Chen | 715e675 | 2025-06-18 19:30:25 | [diff] [blame] | 191 | // ChromeOS FilesApp must include the custom 'fs/sources', etc data for |
| 192 | // paste that it put on the clipboard during copy (crbug.com/271078230). |
| 193 | if (render_frame_host().GetMainFrame()->GetLastCommittedURL().SchemeIs( |
| 194 | kChromeUIScheme)) { |
| 195 | file_type_only = false; |
| 196 | } |
Georg Neis | 35ff854b | 2024-12-17 02:02:08 | [diff] [blame] | 197 | #endif // BUILDFLAG(IS_CHROMEOS) |
Joel Hockey | 9fe6d6b8 | 2023-06-28 23:11:13 | [diff] [blame] | 198 | |
Haihan Chen | 715e675 | 2025-06-18 19:30:25 | [diff] [blame] | 199 | if (file_type_only) { |
| 200 | types = {ui::kMimeTypeUriList16}; |
| 201 | } else { |
| 202 | clipboard->ReadAvailableTypes(clipboard_buffer, data_endpoint.get(), |
| 203 | &types); |
| 204 | } |
Joel Hockey | b210d8dd | 2021-06-04 23:48:55 | [diff] [blame] | 205 | } |
Darwin Huang | 2d5cff0c | 2020-05-05 00:00:48 | [diff] [blame] | 206 | std::move(callback).Run(types); |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 207 | } |
| 208 | |
Stuart Langley | 4f843cc | 2017-12-04 21:56:54 | [diff] [blame] | 209 | void ClipboardHostImpl::IsFormatAvailable(blink::mojom::ClipboardFormat format, |
Darwin Huang | 5c6614c5 | 2019-08-21 01:20:10 | [diff] [blame] | 210 | ui::ClipboardBuffer clipboard_buffer, |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 211 | IsFormatAvailableCallback callback) { |
Pavol Marko | c73be302 | 2021-07-05 15:41:20 | [diff] [blame] | 212 | ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread(); |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 213 | bool result = false; |
Aya ElAttar | be0e5df | 2020-08-21 08:52:46 | [diff] [blame] | 214 | auto data_endpoint = CreateDataEndpoint(); |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 215 | switch (format) { |
Stuart Langley | 4f843cc | 2017-12-04 21:56:54 | [diff] [blame] | 216 | case blink::mojom::ClipboardFormat::kPlaintext: |
Darwin Huang | 71a469a | 2021-07-21 01:44:32 | [diff] [blame] | 217 | result = |
| 218 | clipboard->IsFormatAvailable(ui::ClipboardFormatType::PlainTextType(), |
| 219 | clipboard_buffer, data_endpoint.get()); |
Xiaohan Wang | 7f8052e0 | 2022-01-14 18:44:28 | [diff] [blame] | 220 | #if BUILDFLAG(IS_WIN) |
Pavol Marko | c73be302 | 2021-07-05 15:41:20 | [diff] [blame] | 221 | result |= clipboard->IsFormatAvailable( |
Darwin Huang | 71a469a | 2021-07-21 01:44:32 | [diff] [blame] | 222 | ui::ClipboardFormatType::PlainTextAType(), clipboard_buffer, |
Aya ElAttar | be0e5df | 2020-08-21 08:52:46 | [diff] [blame] | 223 | data_endpoint.get()); |
Darwin Huang | a29382f | 2020-01-16 06:21:44 | [diff] [blame] | 224 | #endif |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 225 | break; |
Stuart Langley | 4f843cc | 2017-12-04 21:56:54 | [diff] [blame] | 226 | case blink::mojom::ClipboardFormat::kHtml: |
Aya ElAttar | be0e5df | 2020-08-21 08:52:46 | [diff] [blame] | 227 | result = |
Darwin Huang | 71a469a | 2021-07-21 01:44:32 | [diff] [blame] | 228 | clipboard->IsFormatAvailable(ui::ClipboardFormatType::HtmlType(), |
Pavol Marko | c73be302 | 2021-07-05 15:41:20 | [diff] [blame] | 229 | clipboard_buffer, data_endpoint.get()); |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 230 | break; |
Stuart Langley | 4f843cc | 2017-12-04 21:56:54 | [diff] [blame] | 231 | case blink::mojom::ClipboardFormat::kSmartPaste: |
Pavol Marko | c73be302 | 2021-07-05 15:41:20 | [diff] [blame] | 232 | result = clipboard->IsFormatAvailable( |
Darwin Huang | 71a469a | 2021-07-21 01:44:32 | [diff] [blame] | 233 | ui::ClipboardFormatType::WebKitSmartPasteType(), clipboard_buffer, |
Aya ElAttar | be0e5df | 2020-08-21 08:52:46 | [diff] [blame] | 234 | data_endpoint.get()); |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 235 | break; |
Stuart Langley | 4f843cc | 2017-12-04 21:56:54 | [diff] [blame] | 236 | case blink::mojom::ClipboardFormat::kBookmark: |
Xiaohan Wang | 7f8052e0 | 2022-01-14 18:44:28 | [diff] [blame] | 237 | #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) |
Aya ElAttar | be0e5df | 2020-08-21 08:52:46 | [diff] [blame] | 238 | result = |
Darwin Huang | 71a469a | 2021-07-21 01:44:32 | [diff] [blame] | 239 | clipboard->IsFormatAvailable(ui::ClipboardFormatType::UrlType(), |
Pavol Marko | c73be302 | 2021-07-05 15:41:20 | [diff] [blame] | 240 | clipboard_buffer, data_endpoint.get()); |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 241 | #else |
| 242 | result = false; |
| 243 | #endif |
| 244 | break; |
| 245 | } |
| 246 | std::move(callback).Run(result); |
| 247 | } |
| 248 | |
Darwin Huang | 5c6614c5 | 2019-08-21 01:20:10 | [diff] [blame] | 249 | void ClipboardHostImpl::ReadText(ui::ClipboardBuffer clipboard_buffer, |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 250 | ReadTextCallback callback) { |
Roger Tawa | 34dd57f8 | 2022-12-15 23:24:20 | [diff] [blame] | 251 | if (!IsRendererPasteAllowed(clipboard_buffer, render_frame_host())) { |
Jan Wilken Dörrie | aace0cfef | 2021-03-11 22:01:58 | [diff] [blame] | 252 | std::move(callback).Run(std::u16string()); |
Darwin Huang | 6195d04 | 2021-02-12 22:36:00 | [diff] [blame] | 253 | return; |
| 254 | } |
Nancy Xiao | 200f55b | 2023-05-03 13:24:47 | [diff] [blame] | 255 | |
Dominique Fauteux-Chapleau | 16d14fb3 | 2024-02-16 20:55:54 | [diff] [blame] | 256 | ClipboardPasteData clipboard_paste_data; |
Dominique Fauteux-Chapleau | d3bd410 | 2024-02-21 20:09:41 | [diff] [blame] | 257 | clipboard_paste_data.text = |
| 258 | ExtractText(clipboard_buffer, CreateDataEndpoint()); |
Dominique Fauteux-Chapleau | 16d14fb3 | 2024-02-16 20:55:54 | [diff] [blame] | 259 | |
Nancy Xiao | 4f3eae5d6 | 2023-04-25 19:38:59 | [diff] [blame] | 260 | PasteIfPolicyAllowed( |
| 261 | clipboard_buffer, ui::ClipboardFormatType::PlainTextType(), |
| 262 | std::move(clipboard_paste_data), |
| 263 | base::BindOnce( |
Dominique Fauteux-Chapleau | d3bd410 | 2024-02-21 20:09:41 | [diff] [blame] | 264 | [](ReadTextCallback callback, |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 265 | std::optional<ClipboardPasteData> clipboard_paste_data) { |
Dominique Fauteux-Chapleau | d3bd410 | 2024-02-21 20:09:41 | [diff] [blame] | 266 | std::u16string result; |
| 267 | if (clipboard_paste_data) { |
| 268 | result = std::move(clipboard_paste_data->text); |
Nancy Xiao | 4f3eae5d6 | 2023-04-25 19:38:59 | [diff] [blame] | 269 | } |
Dominique Fauteux-Chapleau | d3bd410 | 2024-02-21 20:09:41 | [diff] [blame] | 270 | std::move(callback).Run(std::move(result)); |
Nancy Xiao | 4f3eae5d6 | 2023-04-25 19:38:59 | [diff] [blame] | 271 | }, |
Dominique Fauteux-Chapleau | d3bd410 | 2024-02-21 20:09:41 | [diff] [blame] | 272 | std::move(callback))); |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 273 | } |
| 274 | |
Darwin Huang | 5c6614c5 | 2019-08-21 01:20:10 | [diff] [blame] | 275 | void ClipboardHostImpl::ReadHtml(ui::ClipboardBuffer clipboard_buffer, |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 276 | ReadHtmlCallback callback) { |
Roger Tawa | 34dd57f8 | 2022-12-15 23:24:20 | [diff] [blame] | 277 | if (!IsRendererPasteAllowed(clipboard_buffer, render_frame_host())) { |
Jan Wilken Dörrie | aace0cfef | 2021-03-11 22:01:58 | [diff] [blame] | 278 | std::move(callback).Run(std::u16string(), GURL(), 0, 0); |
Darwin Huang | 6195d04 | 2021-02-12 22:36:00 | [diff] [blame] | 279 | return; |
| 280 | } |
Pavol Marko | c73be302 | 2021-07-05 15:41:20 | [diff] [blame] | 281 | ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread(); |
Dominique Fauteux-Chapleau | d3bd410 | 2024-02-21 20:09:41 | [diff] [blame] | 282 | ClipboardPasteData clipboard_paste_data; |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 283 | std::string src_url_str; |
| 284 | uint32_t fragment_start = 0; |
| 285 | uint32_t fragment_end = 0; |
Aya ElAttar | be0e5df | 2020-08-21 08:52:46 | [diff] [blame] | 286 | auto data_dst = CreateDataEndpoint(); |
Dominique Fauteux-Chapleau | d3bd410 | 2024-02-21 20:09:41 | [diff] [blame] | 287 | clipboard->ReadHTML(clipboard_buffer, data_dst.get(), |
| 288 | &clipboard_paste_data.html, &src_url_str, &fragment_start, |
| 289 | &fragment_end); |
Roger Tawa | 03ffdbd | 2020-01-16 18:12:54 | [diff] [blame] | 290 | |
Aya ElAttar | 84e6ef3 | 2021-03-02 16:29:19 | [diff] [blame] | 291 | PasteIfPolicyAllowed( |
Nancy Xiao | 4f3eae5d6 | 2023-04-25 19:38:59 | [diff] [blame] | 292 | clipboard_buffer, ui::ClipboardFormatType::HtmlType(), |
| 293 | std::move(clipboard_paste_data), |
Roger Tawa | 03ffdbd | 2020-01-16 18:12:54 | [diff] [blame] | 294 | base::BindOnce( |
Dominique Fauteux-Chapleau | d3bd410 | 2024-02-21 20:09:41 | [diff] [blame] | 295 | [](std::string src_url_str, uint32_t fragment_start, |
| 296 | uint32_t fragment_end, ReadHtmlCallback callback, |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 297 | std::optional<ClipboardPasteData> clipboard_paste_data) { |
Dominique Fauteux-Chapleau | d3bd410 | 2024-02-21 20:09:41 | [diff] [blame] | 298 | std::u16string markup; |
| 299 | if (clipboard_paste_data) { |
| 300 | markup = std::move(clipboard_paste_data->html); |
Nancy Xiao | 4f3eae5d6 | 2023-04-25 19:38:59 | [diff] [blame] | 301 | } |
Roger Tawa | 03ffdbd | 2020-01-16 18:12:54 | [diff] [blame] | 302 | std::move(callback).Run(std::move(markup), GURL(src_url_str), |
| 303 | fragment_start, fragment_end); |
| 304 | }, |
Dominique Fauteux-Chapleau | d3bd410 | 2024-02-21 20:09:41 | [diff] [blame] | 305 | std::move(src_url_str), fragment_start, fragment_end, |
| 306 | std::move(callback))); |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 307 | } |
| 308 | |
Dylan Sleeper | 27d8f04 | 2020-08-28 02:56:59 | [diff] [blame] | 309 | void ClipboardHostImpl::ReadSvg(ui::ClipboardBuffer clipboard_buffer, |
| 310 | ReadSvgCallback callback) { |
Roger Tawa | 34dd57f8 | 2022-12-15 23:24:20 | [diff] [blame] | 311 | if (!IsRendererPasteAllowed(clipboard_buffer, render_frame_host())) { |
Jan Wilken Dörrie | aace0cfef | 2021-03-11 22:01:58 | [diff] [blame] | 312 | std::move(callback).Run(std::u16string()); |
Darwin Huang | 6195d04 | 2021-02-12 22:36:00 | [diff] [blame] | 313 | return; |
| 314 | } |
Dominique Fauteux-Chapleau | 16d14fb3 | 2024-02-16 20:55:54 | [diff] [blame] | 315 | ClipboardPasteData clipboard_paste_data; |
Dominique Fauteux-Chapleau | d3bd410 | 2024-02-21 20:09:41 | [diff] [blame] | 316 | ui::Clipboard::GetForCurrentThread()->ReadSvg(clipboard_buffer, |
| 317 | /*data_dst=*/nullptr, |
| 318 | &clipboard_paste_data.svg); |
Dominique Fauteux-Chapleau | 16d14fb3 | 2024-02-16 20:55:54 | [diff] [blame] | 319 | |
Nancy Xiao | 4f3eae5d6 | 2023-04-25 19:38:59 | [diff] [blame] | 320 | PasteIfPolicyAllowed( |
| 321 | clipboard_buffer, ui::ClipboardFormatType::SvgType(), |
| 322 | std::move(clipboard_paste_data), |
| 323 | base::BindOnce( |
Dominique Fauteux-Chapleau | d3bd410 | 2024-02-21 20:09:41 | [diff] [blame] | 324 | [](ReadSvgCallback callback, |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 325 | std::optional<ClipboardPasteData> clipboard_paste_data) { |
Dominique Fauteux-Chapleau | d3bd410 | 2024-02-21 20:09:41 | [diff] [blame] | 326 | std::u16string svg; |
| 327 | if (clipboard_paste_data) { |
| 328 | svg = std::move(clipboard_paste_data->svg); |
Nancy Xiao | 4f3eae5d6 | 2023-04-25 19:38:59 | [diff] [blame] | 329 | } |
Dominique Fauteux-Chapleau | d3bd410 | 2024-02-21 20:09:41 | [diff] [blame] | 330 | std::move(callback).Run(std::move(svg)); |
Nancy Xiao | 4f3eae5d6 | 2023-04-25 19:38:59 | [diff] [blame] | 331 | }, |
Dominique Fauteux-Chapleau | d3bd410 | 2024-02-21 20:09:41 | [diff] [blame] | 332 | std::move(callback))); |
Dylan Sleeper | 27d8f04 | 2020-08-28 02:56:59 | [diff] [blame] | 333 | } |
| 334 | |
Darwin Huang | 5c6614c5 | 2019-08-21 01:20:10 | [diff] [blame] | 335 | void ClipboardHostImpl::ReadRtf(ui::ClipboardBuffer clipboard_buffer, |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 336 | ReadRtfCallback callback) { |
Roger Tawa | 34dd57f8 | 2022-12-15 23:24:20 | [diff] [blame] | 337 | if (!IsRendererPasteAllowed(clipboard_buffer, render_frame_host())) { |
Darwin Huang | 6195d04 | 2021-02-12 22:36:00 | [diff] [blame] | 338 | std::move(callback).Run(std::string()); |
| 339 | return; |
| 340 | } |
Roger Tawa | 03ffdbd | 2020-01-16 18:12:54 | [diff] [blame] | 341 | |
Dominique Fauteux-Chapleau | 16d14fb3 | 2024-02-16 20:55:54 | [diff] [blame] | 342 | ClipboardPasteData clipboard_paste_data; |
Dominique Fauteux-Chapleau | d3bd410 | 2024-02-21 20:09:41 | [diff] [blame] | 343 | auto data_dst = CreateDataEndpoint(); |
| 344 | ui::Clipboard::GetForCurrentThread()->ReadRTF( |
| 345 | clipboard_buffer, data_dst.get(), &clipboard_paste_data.rtf); |
Dominique Fauteux-Chapleau | 16d14fb3 | 2024-02-16 20:55:54 | [diff] [blame] | 346 | |
Nancy Xiao | 4f3eae5d6 | 2023-04-25 19:38:59 | [diff] [blame] | 347 | PasteIfPolicyAllowed( |
| 348 | clipboard_buffer, ui::ClipboardFormatType::RtfType(), |
| 349 | std::move(clipboard_paste_data), |
| 350 | base::BindOnce( |
Dominique Fauteux-Chapleau | d3bd410 | 2024-02-21 20:09:41 | [diff] [blame] | 351 | [](ReadRtfCallback callback, |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 352 | std::optional<ClipboardPasteData> clipboard_paste_data) { |
Dominique Fauteux-Chapleau | d3bd410 | 2024-02-21 20:09:41 | [diff] [blame] | 353 | std::string result; |
| 354 | if (clipboard_paste_data) { |
| 355 | result = std::move(clipboard_paste_data->rtf); |
Nancy Xiao | 4f3eae5d6 | 2023-04-25 19:38:59 | [diff] [blame] | 356 | } |
Dominique Fauteux-Chapleau | d3bd410 | 2024-02-21 20:09:41 | [diff] [blame] | 357 | std::move(callback).Run(std::move(result)); |
Nancy Xiao | 4f3eae5d6 | 2023-04-25 19:38:59 | [diff] [blame] | 358 | }, |
Dominique Fauteux-Chapleau | d3bd410 | 2024-02-21 20:09:41 | [diff] [blame] | 359 | std::move(callback))); |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 360 | } |
| 361 | |
Austin Sullivan | fc87089 | 2021-04-29 18:40:11 | [diff] [blame] | 362 | void ClipboardHostImpl::ReadPng(ui::ClipboardBuffer clipboard_buffer, |
| 363 | ReadPngCallback callback) { |
Roger Tawa | 34dd57f8 | 2022-12-15 23:24:20 | [diff] [blame] | 364 | if (!IsRendererPasteAllowed(clipboard_buffer, render_frame_host())) { |
Austin Sullivan | fc87089 | 2021-04-29 18:40:11 | [diff] [blame] | 365 | std::move(callback).Run(mojo_base::BigBuffer()); |
| 366 | return; |
| 367 | } |
| 368 | auto data_dst = CreateDataEndpoint(); |
Pavol Marko | c73be302 | 2021-07-05 15:41:20 | [diff] [blame] | 369 | ui::Clipboard::GetForCurrentThread()->ReadPng( |
| 370 | clipboard_buffer, data_dst.get(), |
| 371 | base::BindOnce(&ClipboardHostImpl::OnReadPng, |
| 372 | weak_ptr_factory_.GetWeakPtr(), clipboard_buffer, |
| 373 | std::move(callback))); |
Austin Sullivan | fc87089 | 2021-04-29 18:40:11 | [diff] [blame] | 374 | } |
| 375 | |
| 376 | void ClipboardHostImpl::OnReadPng(ui::ClipboardBuffer clipboard_buffer, |
| 377 | ReadPngCallback callback, |
| 378 | const std::vector<uint8_t>& data) { |
Nancy Xiao | 200f55b | 2023-05-03 13:24:47 | [diff] [blame] | 379 | // Pass both image and associated text for content analysis. |
Dominique Fauteux-Chapleau | 16d14fb3 | 2024-02-16 20:55:54 | [diff] [blame] | 380 | ClipboardPasteData clipboard_paste_data; |
| 381 | clipboard_paste_data.text = |
| 382 | ExtractText(clipboard_buffer, CreateDataEndpoint()); |
| 383 | clipboard_paste_data.png = data; |
| 384 | |
Austin Sullivan | fc87089 | 2021-04-29 18:40:11 | [diff] [blame] | 385 | PasteIfPolicyAllowed( |
Darwin Huang | 71a469a | 2021-07-21 01:44:32 | [diff] [blame] | 386 | clipboard_buffer, ui::ClipboardFormatType::PngType(), |
Nancy Xiao | 4f3eae5d6 | 2023-04-25 19:38:59 | [diff] [blame] | 387 | std::move(clipboard_paste_data), |
Austin Sullivan | fc87089 | 2021-04-29 18:40:11 | [diff] [blame] | 388 | base::BindOnce( |
Dominique Fauteux-Chapleau | d3bd410 | 2024-02-21 20:09:41 | [diff] [blame] | 389 | [](ReadPngCallback callback, |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 390 | std::optional<ClipboardPasteData> clipboard_paste_data) { |
Nancy Xiao | 4f3eae5d6 | 2023-04-25 19:38:59 | [diff] [blame] | 391 | if (!clipboard_paste_data.has_value()) { |
Austin Sullivan | fc87089 | 2021-04-29 18:40:11 | [diff] [blame] | 392 | std::move(callback).Run(mojo_base::BigBuffer()); |
| 393 | return; |
| 394 | } |
Dominique Fauteux-Chapleau | d3bd410 | 2024-02-21 20:09:41 | [diff] [blame] | 395 | std::move(callback).Run( |
| 396 | mojo_base::BigBuffer(std::move(clipboard_paste_data->png))); |
Austin Sullivan | fc87089 | 2021-04-29 18:40:11 | [diff] [blame] | 397 | }, |
Dominique Fauteux-Chapleau | d3bd410 | 2024-02-21 20:09:41 | [diff] [blame] | 398 | std::move(callback))); |
Austin Sullivan | fc87089 | 2021-04-29 18:40:11 | [diff] [blame] | 399 | } |
Austin Sullivan | 921b54d3 | 2021-10-06 13:59:43 | [diff] [blame] | 400 | |
Joel Hockey | 4c0cb8c | 2021-02-22 02:59:59 | [diff] [blame] | 401 | void ClipboardHostImpl::ReadFiles(ui::ClipboardBuffer clipboard_buffer, |
| 402 | ReadFilesCallback callback) { |
| 403 | blink::mojom::ClipboardFilesPtr result = blink::mojom::ClipboardFiles::New(); |
Roger Tawa | 34dd57f8 | 2022-12-15 23:24:20 | [diff] [blame] | 404 | if (!IsRendererPasteAllowed(clipboard_buffer, render_frame_host())) { |
Joel Hockey | 4c0cb8c | 2021-02-22 02:59:59 | [diff] [blame] | 405 | std::move(callback).Run(std::move(result)); |
| 406 | return; |
| 407 | } |
| 408 | |
Pavol Marko | c73be302 | 2021-07-05 15:41:20 | [diff] [blame] | 409 | ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread(); |
Joel Hockey | 4c0cb8c | 2021-02-22 02:59:59 | [diff] [blame] | 410 | std::vector<ui::FileInfo> filenames; |
| 411 | auto data_dst = CreateDataEndpoint(); |
Pavol Marko | c73be302 | 2021-07-05 15:41:20 | [diff] [blame] | 412 | clipboard->ReadFilenames(clipboard_buffer, data_dst.get(), &filenames); |
Roger Tawa | c617026 | 2022-10-28 23:48:52 | [diff] [blame] | 413 | |
Luca Accorsi | b52ca00 | 2023-12-01 08:54:26 | [diff] [blame] | 414 | // Convert the vector of ui::FileInfo into a vector of base::FilePath so that |
Roger Tawa | c617026 | 2022-10-28 23:48:52 | [diff] [blame] | 415 | // it can be passed to PerformPasteIfContentAllowed() for analysis. When |
| 416 | // the latter is called with ui::ClipboardFormatType::FilenamesType() the |
| 417 | // data to be analyzed is expected to be a newline-separated list of full |
| 418 | // paths. |
Luca Accorsi | b52ca00 | 2023-12-01 08:54:26 | [diff] [blame] | 419 | std::vector<base::FilePath> paths; |
Roger Tawa | c617026 | 2022-10-28 23:48:52 | [diff] [blame] | 420 | paths.reserve(filenames.size()); |
Peter Kasting | 1557e5f | 2025-01-28 01:14:08 | [diff] [blame] | 421 | std::ranges::transform(filenames, std::back_inserter(paths), |
| 422 | [](const ui::FileInfo& info) { return info.path; }); |
Dominique Fauteux-Chapleau | 16d14fb3 | 2024-02-16 20:55:54 | [diff] [blame] | 423 | ClipboardPasteData clipboard_paste_data; |
| 424 | clipboard_paste_data.file_paths = std::move(paths); |
Joel Hockey | 4c0cb8c | 2021-02-22 02:59:59 | [diff] [blame] | 425 | |
Joel Hockey | 4c0cb8c | 2021-02-22 02:59:59 | [diff] [blame] | 426 | // This code matches the drag-and-drop DataTransfer code in |
| 427 | // RenderWidgetHostImpl::DragTargetDrop(). |
| 428 | |
Joel Hockey | d75d506 | 2021-02-23 19:53:25 | [diff] [blame] | 429 | // Call PrepareDataTransferFilenamesForChildProcess() to register files so |
| 430 | // they can be accessed by the renderer. |
danakj | c70aec1f | 2022-07-07 15:48:19 | [diff] [blame] | 431 | RenderProcessHost* process = render_frame_host().GetProcess(); |
Joel Hockey | d75d506 | 2021-02-23 19:53:25 | [diff] [blame] | 432 | result->file_system_id = PrepareDataTransferFilenamesForChildProcess( |
| 433 | filenames, ChildProcessSecurityPolicyImpl::GetInstance(), |
Emily Andrews | d15fd76 | 2024-12-10 20:41:54 | [diff] [blame] | 434 | process->GetDeprecatedID(), |
| 435 | process->GetStoragePartition()->GetFileSystemContext()); |
Joel Hockey | d75d506 | 2021-02-23 19:53:25 | [diff] [blame] | 436 | |
| 437 | // Convert to DataTransferFiles which creates the access token for each file. |
Joel Hockey | 4c0cb8c | 2021-02-22 02:59:59 | [diff] [blame] | 438 | StoragePartitionImpl* storage_partition = static_cast<StoragePartitionImpl*>( |
danakj | c70aec1f | 2022-07-07 15:48:19 | [diff] [blame] | 439 | render_frame_host().GetProcess()->GetStoragePartition()); |
Joel Hockey | d75d506 | 2021-02-23 19:53:25 | [diff] [blame] | 440 | std::vector<blink::mojom::DataTransferFilePtr> files = |
| 441 | FileInfosToDataTransferFiles( |
| 442 | filenames, storage_partition->GetFileSystemAccessManager(), |
Emily Andrews | d15fd76 | 2024-12-10 20:41:54 | [diff] [blame] | 443 | process->GetDeprecatedID()); |
Joel Hockey | d75d506 | 2021-02-23 19:53:25 | [diff] [blame] | 444 | std::move(files.begin(), files.end(), std::back_inserter(result->files)); |
Joel Hockey | 4c0cb8c | 2021-02-22 02:59:59 | [diff] [blame] | 445 | |
Luca Accorsi | a0f03e5 | 2023-12-03 08:55:46 | [diff] [blame] | 446 | PasteIfPolicyAllowed( |
| 447 | clipboard_buffer, ui::ClipboardFormatType::FilenamesType(), |
| 448 | std::move(clipboard_paste_data), |
Joel Hockey | 4c0cb8c | 2021-02-22 02:59:59 | [diff] [blame] | 449 | base::BindOnce( |
| 450 | [](blink::mojom::ClipboardFilesPtr result, ReadFilesCallback callback, |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 451 | std::optional<ClipboardPasteData> clipboard_paste_data) { |
Nancy Xiao | 4f3eae5d6 | 2023-04-25 19:38:59 | [diff] [blame] | 452 | if (!clipboard_paste_data) { |
Joel Hockey | 4c0cb8c | 2021-02-22 02:59:59 | [diff] [blame] | 453 | result->files.clear(); |
| 454 | result->file_system_id->clear(); |
Roger Tawa | c617026 | 2022-10-28 23:48:52 | [diff] [blame] | 455 | } else { |
| 456 | // A subset of the files can be copied. Remove any files that |
| 457 | // should be blocked. First build a list of the files that are |
| 458 | // allowed. |
Luca Accorsi | b52ca00 | 2023-12-01 08:54:26 | [diff] [blame] | 459 | std::set<base::FilePath> allowed_files( |
| 460 | std::move_iterator(clipboard_paste_data->file_paths.begin()), |
| 461 | std::move_iterator(clipboard_paste_data->file_paths.end())); |
Roger Tawa | c617026 | 2022-10-28 23:48:52 | [diff] [blame] | 462 | |
| 463 | for (auto it = result->files.begin(); |
| 464 | it != result->files.end();) { |
Luca Accorsi | b52ca00 | 2023-12-01 08:54:26 | [diff] [blame] | 465 | if (allowed_files.find(it->get()->path) != |
Roger Tawa | c617026 | 2022-10-28 23:48:52 | [diff] [blame] | 466 | allowed_files.end()) { |
| 467 | it = std::next(it); |
| 468 | } else { |
| 469 | it = result->files.erase(it); |
| 470 | } |
| 471 | } |
Joel Hockey | 4c0cb8c | 2021-02-22 02:59:59 | [diff] [blame] | 472 | } |
| 473 | std::move(callback).Run(std::move(result)); |
| 474 | }, |
| 475 | std::move(result), std::move(callback))); |
| 476 | } |
| 477 | |
Anupam Snigdha | 3c3f0844 | 2024-06-14 18:58:29 | [diff] [blame] | 478 | void ClipboardHostImpl::ReadDataTransferCustomData( |
| 479 | ui::ClipboardBuffer clipboard_buffer, |
| 480 | const std::u16string& type, |
| 481 | ReadDataTransferCustomDataCallback callback) { |
Roger Tawa | 34dd57f8 | 2022-12-15 23:24:20 | [diff] [blame] | 482 | if (!IsRendererPasteAllowed(clipboard_buffer, render_frame_host())) { |
Jan Wilken Dörrie | aace0cfef | 2021-03-11 22:01:58 | [diff] [blame] | 483 | std::move(callback).Run(std::u16string()); |
Darwin Huang | 6195d04 | 2021-02-12 22:36:00 | [diff] [blame] | 484 | return; |
| 485 | } |
Roger Tawa | 03ffdbd | 2020-01-16 18:12:54 | [diff] [blame] | 486 | |
Dominique Fauteux-Chapleau | 16d14fb3 | 2024-02-16 20:55:54 | [diff] [blame] | 487 | ClipboardPasteData clipboard_paste_data; |
Dominique Fauteux-Chapleau | d3bd410 | 2024-02-21 20:09:41 | [diff] [blame] | 488 | auto data_dst = CreateDataEndpoint(); |
Anupam Snigdha | 3c3f0844 | 2024-06-14 18:58:29 | [diff] [blame] | 489 | ui::Clipboard::GetForCurrentThread()->ReadDataTransferCustomData( |
Dominique Fauteux-Chapleau | d3bd410 | 2024-02-21 20:09:41 | [diff] [blame] | 490 | clipboard_buffer, type, data_dst.get(), |
| 491 | &clipboard_paste_data.custom_data[type]); |
Dominique Fauteux-Chapleau | 16d14fb3 | 2024-02-16 20:55:54 | [diff] [blame] | 492 | |
Aya ElAttar | 84e6ef3 | 2021-03-02 16:29:19 | [diff] [blame] | 493 | PasteIfPolicyAllowed( |
Anupam Snigdha | e61adbb | 2024-06-13 07:55:53 | [diff] [blame] | 494 | clipboard_buffer, ui::ClipboardFormatType::DataTransferCustomType(), |
Nancy Xiao | 4f3eae5d6 | 2023-04-25 19:38:59 | [diff] [blame] | 495 | std::move(clipboard_paste_data), |
Roger Tawa | 03ffdbd | 2020-01-16 18:12:54 | [diff] [blame] | 496 | base::BindOnce( |
Anupam Snigdha | 3c3f0844 | 2024-06-14 18:58:29 | [diff] [blame] | 497 | [](ReadDataTransferCustomDataCallback callback, |
| 498 | const std::u16string& type, |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 499 | std::optional<ClipboardPasteData> clipboard_paste_data) { |
Dominique Fauteux-Chapleau | d3bd410 | 2024-02-21 20:09:41 | [diff] [blame] | 500 | std::u16string result; |
| 501 | if (clipboard_paste_data) { |
| 502 | result = std::move(clipboard_paste_data->custom_data[type]); |
Nancy Xiao | 4f3eae5d6 | 2023-04-25 19:38:59 | [diff] [blame] | 503 | } |
Dominique Fauteux-Chapleau | d3bd410 | 2024-02-21 20:09:41 | [diff] [blame] | 504 | std::move(callback).Run(std::move(result)); |
Roger Tawa | 03ffdbd | 2020-01-16 18:12:54 | [diff] [blame] | 505 | }, |
Dominique Fauteux-Chapleau | d3bd410 | 2024-02-21 20:09:41 | [diff] [blame] | 506 | std::move(callback), type)); |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 507 | } |
| 508 | |
Jan Wilken Dörrie | aace0cfef | 2021-03-11 22:01:58 | [diff] [blame] | 509 | void ClipboardHostImpl::WriteText(const std::u16string& text) { |
Dominique Fauteux-Chapleau | 88798b9 | 2024-03-14 20:22:10 | [diff] [blame] | 510 | ClipboardPasteData data; |
| 511 | data.text = text; |
Dominique Fauteux-Chapleau | 3685eb1 | 2024-05-03 17:46:18 | [diff] [blame] | 512 | ++pending_writes_; |
Dominique Fauteux-Chapleau | f6e59f2 | 2024-02-05 19:57:53 | [diff] [blame] | 513 | GetContentClient()->browser()->IsClipboardCopyAllowedByPolicy( |
| 514 | CreateClipboardEndpoint(), |
| 515 | { |
| 516 | .size = text.size() * sizeof(std::u16string::value_type), |
| 517 | .format_type = ui::ClipboardFormatType::PlainTextType(), |
| 518 | }, |
Dominique Fauteux-Chapleau | 88798b9 | 2024-03-14 20:22:10 | [diff] [blame] | 519 | data, |
Dominique Fauteux-Chapleau | 302580f | 2024-04-03 20:51:16 | [diff] [blame] | 520 | base::BindOnce(&ClipboardHostImpl::OnCopyAllowedResult, |
Dominique Fauteux-Chapleau | f6e59f2 | 2024-02-05 19:57:53 | [diff] [blame] | 521 | weak_ptr_factory_.GetWeakPtr())); |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 522 | } |
| 523 | |
Jan Wilken Dörrie | aace0cfef | 2021-03-11 22:01:58 | [diff] [blame] | 524 | void ClipboardHostImpl::WriteHtml(const std::u16string& markup, |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 525 | const GURL& url) { |
Dominique Fauteux-Chapleau | 88798b9 | 2024-03-14 20:22:10 | [diff] [blame] | 526 | ClipboardPasteData data; |
| 527 | data.html = markup; |
Dominique Fauteux-Chapleau | 3685eb1 | 2024-05-03 17:46:18 | [diff] [blame] | 528 | ++pending_writes_; |
Dominique Fauteux-Chapleau | f6e59f2 | 2024-02-05 19:57:53 | [diff] [blame] | 529 | GetContentClient()->browser()->IsClipboardCopyAllowedByPolicy( |
| 530 | CreateClipboardEndpoint(), |
| 531 | { |
| 532 | .size = markup.size() * sizeof(std::u16string::value_type), |
| 533 | .format_type = ui::ClipboardFormatType::HtmlType(), |
| 534 | }, |
Dominique Fauteux-Chapleau | 88798b9 | 2024-03-14 20:22:10 | [diff] [blame] | 535 | data, |
Dominique Fauteux-Chapleau | f6e59f2 | 2024-02-05 19:57:53 | [diff] [blame] | 536 | base::BindOnce(&ClipboardHostImpl::OnCopyHtmlAllowedResult, |
| 537 | weak_ptr_factory_.GetWeakPtr(), url)); |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 538 | } |
| 539 | |
Jan Wilken Dörrie | aace0cfef | 2021-03-11 22:01:58 | [diff] [blame] | 540 | void ClipboardHostImpl::WriteSvg(const std::u16string& markup) { |
Dominique Fauteux-Chapleau | 302580f | 2024-04-03 20:51:16 | [diff] [blame] | 541 | ClipboardPasteData data; |
| 542 | data.svg = markup; |
Dominique Fauteux-Chapleau | 3685eb1 | 2024-05-03 17:46:18 | [diff] [blame] | 543 | ++pending_writes_; |
Dominique Fauteux-Chapleau | 302580f | 2024-04-03 20:51:16 | [diff] [blame] | 544 | GetContentClient()->browser()->IsClipboardCopyAllowedByPolicy( |
| 545 | CreateClipboardEndpoint(), |
| 546 | { |
| 547 | .size = markup.size() * sizeof(std::u16string::value_type), |
| 548 | .format_type = ui::ClipboardFormatType::SvgType(), |
| 549 | }, |
| 550 | data, |
| 551 | base::BindOnce(&ClipboardHostImpl::OnCopyAllowedResult, |
| 552 | weak_ptr_factory_.GetWeakPtr())); |
Dylan Sleeper | 27d8f04 | 2020-08-28 02:56:59 | [diff] [blame] | 553 | } |
| 554 | |
Darwin Huang | 53e59b4 | 2019-04-27 03:23:42 | [diff] [blame] | 555 | void ClipboardHostImpl::WriteSmartPasteMarker() { |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 556 | clipboard_writer_->WriteWebSmartPaste(); |
| 557 | } |
| 558 | |
Anupam Snigdha | 56968e7 | 2024-06-18 16:40:36 | [diff] [blame] | 559 | void ClipboardHostImpl::WriteDataTransferCustomData( |
Jan Wilken Dörrie | aace0cfef | 2021-03-11 22:01:58 | [diff] [blame] | 560 | const base::flat_map<std::u16string, std::u16string>& data) { |
Dominique Fauteux-Chapleau | 302580f | 2024-04-03 20:51:16 | [diff] [blame] | 561 | ClipboardPasteData clipboard_paste_data; |
| 562 | clipboard_paste_data.custom_data = data; |
| 563 | |
| 564 | size_t total_size = 0; |
| 565 | for (const auto& entry : clipboard_paste_data.custom_data) { |
| 566 | total_size += entry.second.size(); |
| 567 | } |
| 568 | |
Dominique Fauteux-Chapleau | 3685eb1 | 2024-05-03 17:46:18 | [diff] [blame] | 569 | ++pending_writes_; |
Dominique Fauteux-Chapleau | 302580f | 2024-04-03 20:51:16 | [diff] [blame] | 570 | GetContentClient()->browser()->IsClipboardCopyAllowedByPolicy( |
| 571 | CreateClipboardEndpoint(), |
| 572 | { |
| 573 | .size = total_size, |
Anupam Snigdha | e61adbb | 2024-06-13 07:55:53 | [diff] [blame] | 574 | .format_type = ui::ClipboardFormatType::DataTransferCustomType(), |
Dominique Fauteux-Chapleau | 302580f | 2024-04-03 20:51:16 | [diff] [blame] | 575 | }, |
| 576 | clipboard_paste_data, |
| 577 | base::BindOnce(&ClipboardHostImpl::OnCopyAllowedResult, |
| 578 | weak_ptr_factory_.GetWeakPtr())); |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 579 | } |
| 580 | |
Darwin Huang | 53e59b4 | 2019-04-27 03:23:42 | [diff] [blame] | 581 | void ClipboardHostImpl::WriteBookmark(const std::string& url, |
Jan Wilken Dörrie | aace0cfef | 2021-03-11 22:01:58 | [diff] [blame] | 582 | const std::u16string& title) { |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 583 | clipboard_writer_->WriteBookmark(title, url); |
| 584 | } |
| 585 | |
danakj | 56f34c6 | 2020-12-08 19:54:04 | [diff] [blame] | 586 | void ClipboardHostImpl::WriteImage(const SkBitmap& bitmap) { |
Dominique Fauteux-Chapleau | 302580f | 2024-04-03 20:51:16 | [diff] [blame] | 587 | ClipboardPasteData data; |
| 588 | data.bitmap = bitmap; |
Dominique Fauteux-Chapleau | 3685eb1 | 2024-05-03 17:46:18 | [diff] [blame] | 589 | ++pending_writes_; |
Dominique Fauteux-Chapleau | 302580f | 2024-04-03 20:51:16 | [diff] [blame] | 590 | GetContentClient()->browser()->IsClipboardCopyAllowedByPolicy( |
| 591 | CreateClipboardEndpoint(), |
| 592 | { |
| 593 | .size = bitmap.computeByteSize(), |
| 594 | .format_type = ui::ClipboardFormatType::BitmapType(), |
| 595 | }, |
| 596 | std::move(data), |
| 597 | base::BindOnce(&ClipboardHostImpl::OnCopyAllowedResult, |
| 598 | weak_ptr_factory_.GetWeakPtr())); |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 599 | } |
| 600 | |
Darwin Huang | 53e59b4 | 2019-04-27 03:23:42 | [diff] [blame] | 601 | void ClipboardHostImpl::CommitWrite() { |
Dominique Fauteux-Chapleau | 3685eb1 | 2024-05-03 17:46:18 | [diff] [blame] | 602 | if (pending_writes_ != 0) { |
| 603 | // This branch indicates that some callbacks passed to |
| 604 | // `IsClipboardCopyAllowedByPolicy` still haven't been called, so committing |
| 605 | // data to the clipboard should be delayed. |
| 606 | pending_commit_write_ = true; |
| 607 | return; |
| 608 | } |
| 609 | pending_commit_write_ = false; |
| 610 | |
Anupam Snigdha | 5c87758 | 2024-03-15 01:28:59 | [diff] [blame] | 611 | if (render_frame_host().GetBrowserContext()->IsOffTheRecord()) { |
| 612 | clipboard_writer_->MarkAsOffTheRecord(); |
| 613 | } |
Dominique Fauteux-Chapleau | 61a5359 | 2025-01-17 15:21:34 | [diff] [blame] | 614 | ResetClipboardWriter(); |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 615 | } |
| 616 | |
Roger Tawa | 34dd57f8 | 2022-12-15 23:24:20 | [diff] [blame] | 617 | bool ClipboardHostImpl::IsRendererPasteAllowed( |
| 618 | ui::ClipboardBuffer clipboard_buffer, |
| 619 | RenderFrameHost& render_frame_host) { |
Roger Tawa | 34dd57f8 | 2022-12-15 23:24:20 | [diff] [blame] | 620 | return GetContentClient()->browser()->IsClipboardPasteAllowed( |
| 621 | &render_frame_host); |
| 622 | } |
| 623 | |
Anupam Snigdha | 74b68e4 | 2021-08-10 23:35:59 | [diff] [blame] | 624 | void ClipboardHostImpl::ReadAvailableCustomAndStandardFormats( |
| 625 | ReadAvailableCustomAndStandardFormatsCallback callback) { |
Anupam Snigdha | 74b68e4 | 2021-08-10 23:35:59 | [diff] [blame] | 626 | std::vector<std::u16string> format_types = |
| 627 | ui::Clipboard::GetForCurrentThread() |
Anupam Snigdha | 8aa9dc9 | 2021-09-20 19:23:33 | [diff] [blame] | 628 | ->ReadAvailableStandardAndCustomFormatNames( |
Anupam Snigdha | 74b68e4 | 2021-08-10 23:35:59 | [diff] [blame] | 629 | ui::ClipboardBuffer::kCopyPaste, CreateDataEndpoint().get()); |
| 630 | std::move(callback).Run(format_types); |
| 631 | } |
| 632 | |
| 633 | void ClipboardHostImpl::ReadUnsanitizedCustomFormat( |
| 634 | const std::u16string& format, |
| 635 | ReadUnsanitizedCustomFormatCallback callback) { |
Anupam Snigdha | 74b68e4 | 2021-08-10 23:35:59 | [diff] [blame] | 636 | // `kMaxFormatSize` includes the null terminator as well so we check if |
| 637 | // the `format` size is strictly less than `kMaxFormatSize` or not. |
| 638 | if (format.length() >= blink::mojom::ClipboardHost::kMaxFormatSize) |
| 639 | return; |
| 640 | |
| 641 | // Extract the custom format names and then query the web custom format |
| 642 | // corresponding to the MIME type. |
| 643 | std::string format_name = base::UTF16ToASCII(format); |
| 644 | auto data_endpoint = CreateDataEndpoint(); |
| 645 | std::map<std::string, std::string> custom_format_names = |
| 646 | ui::Clipboard::GetForCurrentThread()->ExtractCustomPlatformNames( |
| 647 | ui::ClipboardBuffer::kCopyPaste, data_endpoint.get()); |
| 648 | std::string web_custom_format_string; |
| 649 | if (custom_format_names.find(format_name) != custom_format_names.end()) |
| 650 | web_custom_format_string = custom_format_names[format_name]; |
| 651 | if (web_custom_format_string.empty()) |
| 652 | return; |
| 653 | |
| 654 | std::string result; |
| 655 | ui::Clipboard::GetForCurrentThread()->ReadData( |
Daniel Cheng | 764a8d3 | 2024-12-06 08:59:18 | [diff] [blame] | 656 | ui::ClipboardFormatType::CustomPlatformType(web_custom_format_string), |
Anupam Snigdha | 74b68e4 | 2021-08-10 23:35:59 | [diff] [blame] | 657 | data_endpoint.get(), &result); |
| 658 | if (result.size() >= blink::mojom::ClipboardHost::kMaxDataSize) |
| 659 | return; |
Peter Kasting | 5f6928c | 2024-11-29 21:25:11 | [diff] [blame] | 660 | base::span<const uint8_t> span = base::as_byte_span(result); |
Anupam Snigdha | 74b68e4 | 2021-08-10 23:35:59 | [diff] [blame] | 661 | mojo_base::BigBuffer buffer = mojo_base::BigBuffer(span); |
| 662 | std::move(callback).Run(std::move(buffer)); |
| 663 | } |
| 664 | |
| 665 | void ClipboardHostImpl::WriteUnsanitizedCustomFormat( |
| 666 | const std::u16string& format, |
| 667 | mojo_base::BigBuffer data) { |
Anupam Snigdha | 74b68e4 | 2021-08-10 23:35:59 | [diff] [blame] | 668 | // `kMaxFormatSize` & `kMaxDataSize` includes the null terminator. |
| 669 | if (format.length() >= blink::mojom::ClipboardHost::kMaxFormatSize) |
| 670 | return; |
| 671 | if (data.size() >= blink::mojom::ClipboardHost::kMaxDataSize) |
| 672 | return; |
| 673 | |
| 674 | // The `format` is mapped to user agent defined web custom format before |
| 675 | // writing to the clipboard. This happens in |
| 676 | // `ScopedClipboardWriter::WriteData`. |
| 677 | clipboard_writer_->WriteData(format, std::move(data)); |
| 678 | } |
| 679 | |
Aya ElAttar | 84e6ef3 | 2021-03-02 16:29:19 | [diff] [blame] | 680 | void ClipboardHostImpl::PasteIfPolicyAllowed( |
| 681 | ui::ClipboardBuffer clipboard_buffer, |
| 682 | const ui::ClipboardFormatType& data_type, |
Nancy Xiao | 4f3eae5d6 | 2023-04-25 19:38:59 | [diff] [blame] | 683 | ClipboardPasteData clipboard_paste_data, |
Dominique Fauteux-Chapleau | 4407a85d | 2024-01-05 13:18:58 | [diff] [blame] | 684 | IsClipboardPasteAllowedCallback callback) { |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 685 | std::optional<size_t> data_size; |
Dominique Fauteux-Chapleau | 4407a85d | 2024-01-05 13:18:58 | [diff] [blame] | 686 | if (clipboard_paste_data.file_paths.empty()) { |
Dominique Fauteux-Chapleau | 16d14fb3 | 2024-02-16 20:55:54 | [diff] [blame] | 687 | data_size = clipboard_paste_data.size(); |
Dominique Fauteux-Chapleau | 4407a85d | 2024-01-05 13:18:58 | [diff] [blame] | 688 | } |
| 689 | |
Dominique Fauteux-Chapleau | 859e737d | 2024-04-22 22:00:49 | [diff] [blame] | 690 | ui::ClipboardSequenceNumberToken seqno = |
| 691 | ui::Clipboard::GetForCurrentThread()->GetSequenceNumber(clipboard_buffer); |
| 692 | |
Dominique Fauteux-Chapleau | 61a5359 | 2025-01-17 15:21:34 | [diff] [blame] | 693 | auto data_dst = CreateClipboardEndpoint(); |
| 694 | const ui::DataTransferEndpoint* data_dst_endpoint = |
| 695 | base::OptionalToPtr(data_dst.data_transfer_endpoint()); |
danakj | c70aec1f | 2022-07-07 15:48:19 | [diff] [blame] | 696 | static_cast<RenderFrameHostImpl&>(render_frame_host()) |
Dominique Fauteux-Chapleau | 4407a85d | 2024-01-05 13:18:58 | [diff] [blame] | 697 | .IsClipboardPasteAllowedByPolicy( |
Dominique Fauteux-Chapleau | 61a5359 | 2025-01-17 15:21:34 | [diff] [blame] | 698 | GetSourceClipboardEndpoint(data_dst_endpoint, clipboard_buffer), |
| 699 | std::move(data_dst), |
Dominique Fauteux-Chapleau | 4407a85d | 2024-01-05 13:18:58 | [diff] [blame] | 700 | { |
| 701 | .size = data_size, |
| 702 | .format_type = data_type, |
| 703 | .seqno = seqno, |
| 704 | }, |
Dominique Fauteux-Chapleau | 859e737d | 2024-04-22 22:00:49 | [diff] [blame] | 705 | std::move(clipboard_paste_data), std::move(callback)); |
Roger Tawa | 03ffdbd | 2020-01-16 18:12:54 | [diff] [blame] | 706 | } |
| 707 | |
Dominique Fauteux-Chapleau | f6e59f2 | 2024-02-05 19:57:53 | [diff] [blame] | 708 | void ClipboardHostImpl::OnCopyHtmlAllowedResult( |
| 709 | const GURL& source_url, |
Dominique Fauteux-Chapleau | 302580f | 2024-04-03 20:51:16 | [diff] [blame] | 710 | const ui::ClipboardFormatType& data_type, |
Dominique Fauteux-Chapleau | 88798b9 | 2024-03-14 20:22:10 | [diff] [blame] | 711 | const ClipboardPasteData& data, |
Dominique Fauteux-Chapleau | f6e59f2 | 2024-02-05 19:57:53 | [diff] [blame] | 712 | std::optional<std::u16string> replacement_data) { |
Dominique Fauteux-Chapleau | 3685eb1 | 2024-05-03 17:46:18 | [diff] [blame] | 713 | DCHECK_GT(pending_writes_, 0); |
| 714 | --pending_writes_; |
| 715 | |
Dominique Fauteux-Chapleau | 1f19c23 | 2025-03-13 16:59:10 | [diff] [blame] | 716 | AddSourceDataToClipboardWriter(); |
Dominique Fauteux-Chapleau | 302580f | 2024-04-03 20:51:16 | [diff] [blame] | 717 | |
Dominique Fauteux-Chapleau | f6e59f2 | 2024-02-05 19:57:53 | [diff] [blame] | 718 | if (replacement_data) { |
| 719 | clipboard_writer_->WriteText(std::move(*replacement_data)); |
Dominique Fauteux-Chapleau | 3685eb1 | 2024-05-03 17:46:18 | [diff] [blame] | 720 | } else { |
| 721 | clipboard_writer_->WriteHTML(data.html, source_url.spec()); |
Dominique Fauteux-Chapleau | 302580f | 2024-04-03 20:51:16 | [diff] [blame] | 722 | } |
Dominique Fauteux-Chapleau | 3685eb1 | 2024-05-03 17:46:18 | [diff] [blame] | 723 | if (pending_commit_write_) { |
| 724 | CommitWrite(); |
| 725 | } |
Dominique Fauteux-Chapleau | 302580f | 2024-04-03 20:51:16 | [diff] [blame] | 726 | } |
| 727 | |
| 728 | void ClipboardHostImpl::OnCopyAllowedResult( |
| 729 | const ui::ClipboardFormatType& data_type, |
| 730 | const ClipboardPasteData& data, |
| 731 | std::optional<std::u16string> replacement_data) { |
Dominique Fauteux-Chapleau | 3685eb1 | 2024-05-03 17:46:18 | [diff] [blame] | 732 | DCHECK_GT(pending_writes_, 0); |
| 733 | --pending_writes_; |
| 734 | |
Dominique Fauteux-Chapleau | 1f19c23 | 2025-03-13 16:59:10 | [diff] [blame] | 735 | AddSourceDataToClipboardWriter(); |
Dominique Fauteux-Chapleau | 302580f | 2024-04-03 20:51:16 | [diff] [blame] | 736 | |
Dominique Fauteux-Chapleau | 3685eb1 | 2024-05-03 17:46:18 | [diff] [blame] | 737 | // If `replacement_data` is empty, only one of these fields should be |
| 738 | // non-empty depending on which "Write" method was called by the renderer. |
Dominique Fauteux-Chapleau | 302580f | 2024-04-03 20:51:16 | [diff] [blame] | 739 | if (replacement_data) { |
| 740 | // `replacement_data` having a value implies the copy was not allowed and |
| 741 | // that a warning message should instead be put into the clipboard. |
| 742 | clipboard_writer_->WriteText(std::move(*replacement_data)); |
Dominique Fauteux-Chapleau | 3685eb1 | 2024-05-03 17:46:18 | [diff] [blame] | 743 | } else if (data_type == ui::ClipboardFormatType::PlainTextType()) { |
Dominique Fauteux-Chapleau | 302580f | 2024-04-03 20:51:16 | [diff] [blame] | 744 | // This branch should be reached only after `WriteText()` is called. |
| 745 | clipboard_writer_->WriteText(data.text); |
| 746 | } else if (data_type == ui::ClipboardFormatType::SvgType()) { |
| 747 | // This branch should be reached only after `WriteSvg()` is called. |
| 748 | clipboard_writer_->WriteSvg(data.svg); |
| 749 | } else if (data_type == ui::ClipboardFormatType::BitmapType()) { |
| 750 | // This branch should be reached only after `WriteImage()` is called. |
| 751 | clipboard_writer_->WriteImage(data.bitmap); |
Anupam Snigdha | e61adbb | 2024-06-13 07:55:53 | [diff] [blame] | 752 | } else if (data_type == ui::ClipboardFormatType::DataTransferCustomType()) { |
Dominique Fauteux-Chapleau | 302580f | 2024-04-03 20:51:16 | [diff] [blame] | 753 | // This branch should be reached only after `WriteCustomData()` is called. |
| 754 | base::Pickle pickle; |
| 755 | ui::WriteCustomDataToPickle(data.custom_data, &pickle); |
| 756 | clipboard_writer_->WritePickledData( |
Anupam Snigdha | e61adbb | 2024-06-13 07:55:53 | [diff] [blame] | 757 | pickle, ui::ClipboardFormatType::DataTransferCustomType()); |
Dominique Fauteux-Chapleau | f6e59f2 | 2024-02-05 19:57:53 | [diff] [blame] | 758 | } else { |
Peter Boström | fc7ddc18 | 2024-10-31 19:37:21 | [diff] [blame] | 759 | NOTREACHED(); |
Anthony Vallee-Dubois | ac84770 | 2021-12-06 21:00:48 | [diff] [blame] | 760 | } |
Dominique Fauteux-Chapleau | 3685eb1 | 2024-05-03 17:46:18 | [diff] [blame] | 761 | |
| 762 | if (pending_commit_write_) { |
| 763 | CommitWrite(); |
| 764 | } |
siashah | 1cac9c5 | 2024-07-09 23:50:36 | [diff] [blame] | 765 | |
| 766 | // Notify the observer that the write was committed to the clipboard. We do |
| 767 | // this only for text copies but it can be extended to other types if needed. |
| 768 | if (!replacement_data && |
| 769 | data_type == ui::ClipboardFormatType::PlainTextType()) { |
| 770 | static_cast<RenderFrameHostImpl&>(render_frame_host()) |
| 771 | .OnTextCopiedToClipboard(data.text); |
| 772 | } |
Anthony Vallee-Dubois | ac84770 | 2021-12-06 21:00:48 | [diff] [blame] | 773 | } |
| 774 | |
Dominique Fauteux-Chapleau | 2cdc6a9 | 2024-01-29 17:39:37 | [diff] [blame] | 775 | std::unique_ptr<ui::DataTransferEndpoint> |
| 776 | ClipboardHostImpl::CreateDataEndpoint() { |
Dominique Fauteux-Chapleau | d92e1fe | 2024-06-25 20:20:05 | [diff] [blame] | 777 | if (!render_frame_host().GetMainFrame()->GetLastCommittedURL().is_valid()) { |
| 778 | return nullptr; |
| 779 | } |
| 780 | |
Alexander Timin | e3383d0 | 2021-06-24 19:57:59 | [diff] [blame] | 781 | return std::make_unique<ui::DataTransferEndpoint>( |
danakj | c70aec1f | 2022-07-07 15:48:19 | [diff] [blame] | 782 | render_frame_host().GetMainFrame()->GetLastCommittedURL(), |
Dominique Fauteux-Chapleau | 5e305e8 | 2024-06-21 00:02:03 | [diff] [blame] | 783 | ui::DataTransferEndpointOptions{ |
| 784 | .notify_if_restricted = |
| 785 | render_frame_host().HasTransientUserActivation(), |
| 786 | .off_the_record = |
| 787 | render_frame_host().GetBrowserContext()->IsOffTheRecord(), |
| 788 | }); |
Aya ElAttar | be0e5df | 2020-08-21 08:52:46 | [diff] [blame] | 789 | } |
Dominique Fauteux-Chapleau | f6e59f2 | 2024-02-05 19:57:53 | [diff] [blame] | 790 | |
| 791 | ClipboardEndpoint ClipboardHostImpl::CreateClipboardEndpoint() { |
| 792 | return ClipboardEndpoint( |
| 793 | CreateDataEndpoint().get(), |
| 794 | base::BindRepeating( |
| 795 | [](GlobalRenderFrameHostId rfh_id) -> BrowserContext* { |
| 796 | auto* rfh = RenderFrameHost::FromID(rfh_id); |
| 797 | if (!rfh) { |
| 798 | return nullptr; |
| 799 | } |
| 800 | return rfh->GetBrowserContext(); |
| 801 | }, |
| 802 | render_frame_host().GetGlobalId()), |
| 803 | render_frame_host()); |
| 804 | } |
| 805 | |
Dominique Fauteux-Chapleau | 61a5359 | 2025-01-17 15:21:34 | [diff] [blame] | 806 | void ClipboardHostImpl::ResetClipboardWriter() { |
| 807 | clipboard_writer_ = std::make_unique<ui::ScopedClipboardWriter>( |
| 808 | ui::ClipboardBuffer::kCopyPaste, CreateDataEndpoint()); |
Dominique Fauteux-Chapleau | 1f19c23 | 2025-03-13 16:59:10 | [diff] [blame] | 809 | } |
| 810 | |
| 811 | void ClipboardHostImpl::AddSourceDataToClipboardWriter() { |
| 812 | clipboard_writer_->SetDataSourceURL( |
| 813 | render_frame_host().GetMainFrame()->GetLastCommittedURL(), |
| 814 | render_frame_host().GetLastCommittedURL()); |
Dominique Fauteux-Chapleau | 61a5359 | 2025-01-17 15:21:34 | [diff] [blame] | 815 | clipboard_writer_->WritePickledData( |
| 816 | render_frame_host().GetGlobalFrameToken().ToPickle(), |
| 817 | SourceRFHTokenType()); |
| 818 | } |
| 819 | |
Rohan Raja | 183dfd9 | 2025-04-22 21:41:09 | [diff] [blame] | 820 | void ClipboardHostImpl::OnClipboardDataChanged() { |
| 821 | if (!listening_to_clipboard_) { |
| 822 | return; |
| 823 | } |
| 824 | if (clipboard_listener_) { |
| 825 | clipboard_listener_->OnClipboardDataChanged(); |
| 826 | } |
| 827 | } |
| 828 | |
| 829 | void ClipboardHostImpl::RegisterClipboardListener( |
| 830 | mojo::PendingRemote<blink::mojom::ClipboardListener> listener) { |
| 831 | // Replace the current listener with the new one |
| 832 | clipboard_listener_.reset(); |
| 833 | clipboard_listener_.Bind(std::move(listener)); |
| 834 | |
| 835 | // Set up connection error handler to stop observing when connection is closed |
| 836 | clipboard_listener_.set_disconnect_handler( |
| 837 | base::BindOnce(&ClipboardHostImpl::StopObservingClipboard, |
| 838 | weak_ptr_factory_.GetWeakPtr())); |
| 839 | |
| 840 | // Start listening for clipboard changes if not already doing so |
| 841 | if (!listening_to_clipboard_) { |
| 842 | ui::ClipboardMonitor::GetInstance()->AddObserver(this); |
| 843 | listening_to_clipboard_ = true; |
| 844 | } |
| 845 | } |
| 846 | |
| 847 | void ClipboardHostImpl::StopObservingClipboard() { |
| 848 | if (listening_to_clipboard_) { |
| 849 | ui::ClipboardMonitor::GetInstance()->RemoveObserver(this); |
| 850 | listening_to_clipboard_ = false; |
| 851 | } |
| 852 | clipboard_listener_.reset(); |
| 853 | } |
| 854 | |
Stuart Langley | e830001 | 2017-11-24 01:16:18 | [diff] [blame] | 855 | } // namespace content |