blob: fc27340d6b810eb9f1990b1886ed8d340d701634 [file] [log] [blame]
Avi Drissman4e1b7bc32022-09-15 14:03:501// Copyright 2012 The Chromium Authors
danakjc492bf82020-09-09 20:02:442// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CONTENT_BROWSER_RENDERER_HOST_CLIPBOARD_HOST_IMPL_H_
6#define CONTENT_BROWSER_RENDERER_HOST_CLIPBOARD_HOST_IMPL_H_
7
8#include <map>
9#include <memory>
Arthur Sonzognic686e8f2024-01-11 08:36:3710#include <optional>
danakjc492bf82020-09-09 20:02:4411#include <string>
12#include <vector>
13
Avi Drissmanadac21992023-01-11 23:46:3914#include "base/functional/callback_forward.h"
Daniel Chengd4c3eab2021-08-31 18:39:0115#include "base/gtest_prod_util.h"
danakjc492bf82020-09-09 20:02:4416#include "base/memory/weak_ptr.h"
danakjc492bf82020-09-09 20:02:4417#include "base/time/time.h"
18#include "build/build_config.h"
19#include "content/browser/renderer_host/render_frame_host_impl.h"
20#include "content/common/content_export.h"
Dominique Fauteux-Chapleau88798b92024-03-14 20:22:1021#include "content/public/browser/clipboard_types.h"
Daniel Cheng9fb887ff2021-10-01 20:27:3822#include "content/public/browser/document_service.h"
Austin Sullivanfc870892021-04-29 18:40:1123#include "mojo/public/cpp/base/big_buffer.h"
danakjc492bf82020-09-09 20:02:4424#include "mojo/public/cpp/bindings/receiver.h"
Rohan Raja183dfd92025-04-22 21:41:0925#include "mojo/public/cpp/bindings/remote.h"
danakjc492bf82020-09-09 20:02:4426#include "third_party/blink/public/mojom/clipboard/clipboard.mojom.h"
27#include "ui/base/clipboard/clipboard.h"
Rohan Raja183dfd92025-04-22 21:41:0928#include "ui/base/clipboard/clipboard_observer.h"
danakjc492bf82020-09-09 20:02:4429
30class GURL;
31
32namespace ui {
33class ScopedClipboardWriter;
34} // namespace ui
35
36namespace content {
37
38class ClipboardHostImplTest;
39
Dominique Fauteux-Chapleauc174eaa2024-02-12 19:29:2440// Returns a representation of the last source ClipboardEndpoint. This will
Dominique Fauteux-Chapleau61a53592025-01-17 15:21:3441// either match the last clipboard write if there is an RFH token in the
42// clipboard, or an endpoint built from `Clipboard::GetSource()` called with
Dominique Fauteux-Chapleauc174eaa2024-02-12 19:29:2443// `clipboard_buffer` otherwise.
44//
45// //content maintains additional metadata on top of what the //ui layer already
46// tracks about clipboard data's source, e.g. the WebContents that provided the
47// data. This function allows retrieving both the //ui metadata and the
48// //content metadata in a single call.
Dominique Fauteux-Chapleauc174eaa2024-02-12 19:29:2449CONTENT_EXPORT ClipboardEndpoint
Dominique Fauteux-Chapleau61a53592025-01-17 15:21:3450GetSourceClipboardEndpoint(const ui::DataTransferEndpoint* data_dst,
Dominique Fauteux-Chapleauc174eaa2024-02-12 19:29:2451 ui::ClipboardBuffer clipboard_buffer);
52
Alexander Timine3383d02021-06-24 19:57:5953class CONTENT_EXPORT ClipboardHostImpl
Rohan Raja183dfd92025-04-22 21:41:0954 : public DocumentService<blink::mojom::ClipboardHost>,
55 public ui::ClipboardObserver {
danakjc492bf82020-09-09 20:02:4456 public:
57 ~ClipboardHostImpl() override;
58
Rohan Raja183dfd92025-04-22 21:41:0959 // Override for ui::ClipboardObserver
60 void OnClipboardDataChanged() override;
61
danakjc492bf82020-09-09 20:02:4462 static void Create(
63 RenderFrameHost* render_frame_host,
64 mojo::PendingReceiver<blink::mojom::ClipboardHost> receiver);
65
Nancy Xiao4f3eae5d62023-04-25 19:38:5966 using ClipboardPasteData = content::ClipboardPasteData;
67
danakjc492bf82020-09-09 20:02:4468 protected:
69 // These types and methods are protected for testing.
70
Dominique Fauteux-Chapleau4407a85d2024-01-05 13:18:5871 using IsClipboardPasteAllowedCallback =
72 RenderFrameHostImpl::IsClipboardPasteAllowedCallback;
danakjc492bf82020-09-09 20:02:4473
Alexander Timine3383d02021-06-24 19:57:5974 explicit ClipboardHostImpl(
danakjc70aec1f2022-07-07 15:48:1975 RenderFrameHost& render_frame_host,
Alexander Timine3383d02021-06-24 19:57:5976 mojo::PendingReceiver<blink::mojom::ClipboardHost> receiver);
danakjc492bf82020-09-09 20:02:4477
Aya ElAttar84e6ef32021-03-02 16:29:1978 // Performs a check to see if pasting `data` is allowed by data transfer
Dominique Fauteux-Chapleau4407a85d2024-01-05 13:18:5879 // policies and invokes FinishPasteIfAllowed upon completion.
Aya ElAttar84e6ef32021-03-02 16:29:1980 void PasteIfPolicyAllowed(ui::ClipboardBuffer clipboard_buffer,
81 const ui::ClipboardFormatType& data_type,
Nancy Xiao4f3eae5d62023-04-25 19:38:5982 ClipboardPasteData clipboard_paste_data,
Dominique Fauteux-Chapleau4407a85d2024-01-05 13:18:5883 IsClipboardPasteAllowedCallback callback);
danakjc492bf82020-09-09 20:02:4484
danakjc492bf82020-09-09 20:02:4485 private:
86 friend class ClipboardHostImplTest;
Dominique Fauteux-Chapleau859e737d2024-04-22 22:00:4987 friend class ClipboardHostImplWriteTest;
Dominique Fauteux-Chapleau3685eb12024-05-03 17:46:1888 friend class ClipboardHostImplAsyncWriteTest;
Rohan Raja183dfd92025-04-22 21:41:0989 friend class ClipboardHostImplChangeTest;
Dominique Fauteux-Chapleau859e737d2024-04-22 22:00:4990
91 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplWriteTest, WriteText);
92 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplWriteTest, WriteText_Empty);
93 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplWriteTest, WriteHtml);
94 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplWriteTest, WriteHtml_Empty);
95 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplWriteTest, WriteSvg);
96 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplWriteTest, WriteSvg_Empty);
97 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplWriteTest, WriteBitmap);
98 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplWriteTest, WriteBitmap_Empty);
Anupam Snigdha56968e72024-06-18 16:40:3699 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplWriteTest,
100 WriteDataTransferCustomData);
101 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplWriteTest,
102 WriteDataTransferCustomData_Empty);
Dominique Fauteux-Chapleau859e737d2024-04-22 22:00:49103 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplWriteTest,
Dominique Fauteux-Chapleau4407a85d2024-01-05 13:18:58104 PerformPasteIfAllowed_EmptyData);
Dominique Fauteux-Chapleau1f19c232025-03-13 16:59:10105 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplWriteTest,
106 NoSourceWithoutDataWrite);
Dominique Fauteux-Chapleau859e737d2024-04-22 22:00:49107 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplWriteTest, MainFrameURL);
108 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplWriteTest, GetSourceEndpoint);
Dominique Fauteux-Chapleau3685eb12024-05-03 17:46:18109 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplAsyncWriteTest, WriteText);
110 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplAsyncWriteTest, WriteHtml);
111 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplAsyncWriteTest, WriteTextAndHtml);
112 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplAsyncWriteTest, ConcurrentWrites);
Rohan Raja183dfd92025-04-22 21:41:09113 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplChangeTest, AddClipboardListener);
114 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplChangeTest,
115 ClipboardListenerDisconnect);
danakjc492bf82020-09-09 20:02:44116
117 // mojom::ClipboardHost
Rohan Raja183dfd92025-04-22 21:41:09118 void RegisterClipboardListener(
119 mojo::PendingRemote<blink::mojom::ClipboardListener> listener) override;
danakjc492bf82020-09-09 20:02:44120 void GetSequenceNumber(ui::ClipboardBuffer clipboard_buffer,
121 GetSequenceNumberCallback callback) override;
122 void IsFormatAvailable(blink::mojom::ClipboardFormat format,
123 ui::ClipboardBuffer clipboard_buffer,
124 IsFormatAvailableCallback callback) override;
125 void ReadAvailableTypes(ui::ClipboardBuffer clipboard_buffer,
126 ReadAvailableTypesCallback callback) override;
127 void ReadText(ui::ClipboardBuffer clipboard_buffer,
128 ReadTextCallback callback) override;
129 void ReadHtml(ui::ClipboardBuffer clipboard_buffer,
130 ReadHtmlCallback callback) override;
131 void ReadSvg(ui::ClipboardBuffer clipboard_buffer,
132 ReadSvgCallback callback) override;
133 void ReadRtf(ui::ClipboardBuffer clipboard_buffer,
134 ReadRtfCallback callback) override;
Austin Sullivanaa060982021-06-25 17:49:30135 void ReadPng(ui::ClipboardBuffer clipboard_buffer,
136 ReadPngCallback callback) override;
Joel Hockey4c0cb8c2021-02-22 02:59:59137 void ReadFiles(ui::ClipboardBuffer clipboard_buffer,
138 ReadFilesCallback callback) override;
Anupam Snigdha3c3f08442024-06-14 18:58:29139 void ReadDataTransferCustomData(
140 ui::ClipboardBuffer clipboard_buffer,
141 const std::u16string& type,
142 ReadDataTransferCustomDataCallback callback) override;
Anupam Snigdha74b68e42021-08-10 23:35:59143 void ReadAvailableCustomAndStandardFormats(
144 ReadAvailableCustomAndStandardFormatsCallback callback) override;
145 void ReadUnsanitizedCustomFormat(
146 const std::u16string& format,
147 ReadUnsanitizedCustomFormatCallback callback) override;
148 void WriteUnsanitizedCustomFormat(const std::u16string& format,
149 mojo_base::BigBuffer data) override;
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58150 void WriteText(const std::u16string& text) override;
151 void WriteHtml(const std::u16string& markup, const GURL& url) override;
152 void WriteSvg(const std::u16string& markup) override;
danakjc492bf82020-09-09 20:02:44153 void WriteSmartPasteMarker() override;
Anupam Snigdha56968e72024-06-18 16:40:36154 void WriteDataTransferCustomData(
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58155 const base::flat_map<std::u16string, std::u16string>& data) override;
danakjc492bf82020-09-09 20:02:44156 void WriteBookmark(const std::string& url,
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58157 const std::u16string& title) override;
danakjbdf1e0a2020-11-10 18:27:47158 void WriteImage(const SkBitmap& unsafe_bitmap) override;
danakjc492bf82020-09-09 20:02:44159 void CommitWrite() override;
Xiaohan Wang7f8052e02022-01-14 18:44:28160#if BUILDFLAG(IS_MAC)
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58161 void WriteStringToFindPboard(const std::u16string& text) override;
Rohan Raja4826d0032025-07-01 14:09:37162 void GetPlatformPermissionState(
163 GetPlatformPermissionStateCallback callback) override;
danakjc492bf82020-09-09 20:02:44164#endif
165
Roger Tawa34dd57f82022-12-15 23:24:20166 // Checks if the renderer allows pasting. This check is skipped if called
167 // soon after a successful content allowed request.
168 bool IsRendererPasteAllowed(ui::ClipboardBuffer clipboard_buffer,
169 RenderFrameHost& render_frame_host);
170
Dominique Fauteux-Chapleau302580f2024-04-03 20:51:16171 // Helper to be used when checking if data is allowed to be copied.
172 //
Dominique Fauteux-Chapleauf6e59f22024-02-05 19:57:53173 // If `replacement_data` is null, `clipboard_writer_` will be used to write
Dominique Fauteux-Chapleau302580f2024-04-03 20:51:16174 // `data` to the clipboard. `data` should only have one of its fields set
175 // depending on which "Write" method lead to `OnCopyAllowedResult()` being
176 // called. That field should correspond to `data_type`.
177 //
178 // If `replacement_data` is not null, instead that replacement string is
179 // written to the clipboard as plaintext.
180 //
181 // This method can be called asynchronously.
Dominique Fauteux-Chapleau3685eb12024-05-03 17:46:18182 virtual void OnCopyAllowedResult(
183 const ui::ClipboardFormatType& data_type,
184 const ClipboardPasteData& data,
185 std::optional<std::u16string> replacement_data);
Dominique Fauteux-Chapleau302580f2024-04-03 20:51:16186
187 // Does the same thing as the previous function with an extra `source_url`
188 // used to propagate the URL obtained in the `WriteHtml()` method call.
189 //
190 // This method can be called asynchronously.
Dominique Fauteux-Chapleau3685eb12024-05-03 17:46:18191 virtual void OnCopyHtmlAllowedResult(
192 const GURL& source_url,
193 const ui::ClipboardFormatType& data_type,
194 const ClipboardPasteData& data,
195 std::optional<std::u16string> replacement_data);
Anthony Vallee-Duboisac847702021-12-06 21:00:48196
Dominique Fauteux-Chapleauf6e59f22024-02-05 19:57:53197 using CopyAllowedCallback = base::OnceCallback<void()>;
Dominique Fauteux-Chapleaudbb4b7092024-02-01 15:42:37198
Austin Sullivanfc870892021-04-29 18:40:11199 void OnReadPng(ui::ClipboardBuffer clipboard_buffer,
200 ReadPngCallback callback,
201 const std::vector<uint8_t>& data);
danakjc492bf82020-09-09 20:02:44202
Dominique Fauteux-Chapleau61a53592025-01-17 15:21:34203 // Resets `clipboard_writer_` to write its data to the clipboard, and
204 // reinitialize it in preparation for the next write.
205 void ResetClipboardWriter();
206
Dominique Fauteux-Chapleau1f19c232025-03-13 16:59:10207 // Adds source-tracking metadata to `clipboard_writer_` so it can be written
208 // to the clipboard on the next `CommitWrite()` call.
209 void AddSourceDataToClipboardWriter();
210
Dominique Fauteux-Chapleau3b7738c2024-01-16 21:08:55211 // Creates a `ui::DataTransferEndpoint` representing the last committed URL.
Dominique Fauteux-Chapleau2cdc6a92024-01-29 17:39:37212 std::unique_ptr<ui::DataTransferEndpoint> CreateDataEndpoint();
danakjc492bf82020-09-09 20:02:44213
Dominique Fauteux-Chapleauf6e59f22024-02-05 19:57:53214 // Creates a `content::ClipboardEndpoint` representing the last committed URL.
215 ClipboardEndpoint CreateClipboardEndpoint();
216
Rohan Raja183dfd92025-04-22 21:41:09217 // Stops observing clipboard changes and resets the listener.
218 void StopObservingClipboard();
219
danakjc492bf82020-09-09 20:02:44220 std::unique_ptr<ui::ScopedClipboardWriter> clipboard_writer_;
221
Dominique Fauteux-Chapleau3685eb12024-05-03 17:46:18222 // Counts the number of expected `Write*` calls to be made to the current
223 // `clipboard_writer_`. This should be used to handle asynchronous `Write*`
224 // calls made by `IsClipboardCopyAllowedByPolicy`.
225 int pending_writes_ = 0;
226
227 // Indicates that the renderer called `CommitWrite()`, but that
228 // `pending_writes_` was not 0 at that time and that it should instead be
229 // called when the last pending `Write*` call is made.
230 bool pending_commit_write_ = false;
231
Rohan Raja183dfd92025-04-22 21:41:09232 // Tracks whether this instance is currently observing clipboard changes.
233 bool listening_to_clipboard_ = false;
234
235 // Single clipboard listener that will be notified on clipboard changes
236 mojo::Remote<blink::mojom::ClipboardListener> clipboard_listener_;
237
danakjc492bf82020-09-09 20:02:44238 base::WeakPtrFactory<ClipboardHostImpl> weak_ptr_factory_{this};
239};
240
241} // namespace content
242
243#endif // CONTENT_BROWSER_RENDERER_HOST_CLIPBOARD_HOST_IMPL_H_