blob: 363b90fba31ca178e73f2a00c21754db8e6ec01e [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>
10#include <string>
11#include <vector>
12
Austin Sullivanfc870892021-04-29 18:40:1113#include "base/callback_forward.h"
Daniel Chengd4c3eab2021-08-31 18:39:0114#include "base/gtest_prod_util.h"
danakjc492bf82020-09-09 20:02:4415#include "base/memory/weak_ptr.h"
danakjc492bf82020-09-09 20:02:4416#include "base/time/time.h"
17#include "build/build_config.h"
18#include "content/browser/renderer_host/render_frame_host_impl.h"
19#include "content/common/content_export.h"
Daniel Cheng9fb887ff2021-10-01 20:27:3820#include "content/public/browser/document_service.h"
Austin Sullivanfc870892021-04-29 18:40:1121#include "mojo/public/cpp/base/big_buffer.h"
danakjc492bf82020-09-09 20:02:4422#include "mojo/public/cpp/bindings/receiver.h"
Anton Bikineevf62d1bf2021-05-15 17:56:0723#include "third_party/abseil-cpp/absl/types/optional.h"
danakjc492bf82020-09-09 20:02:4424#include "third_party/blink/public/mojom/clipboard/clipboard.mojom.h"
25#include "ui/base/clipboard/clipboard.h"
26
27class GURL;
28
29namespace ui {
30class ScopedClipboardWriter;
31} // namespace ui
32
33namespace content {
34
35class ClipboardHostImplTest;
36
Alexander Timine3383d02021-06-24 19:57:5937class CONTENT_EXPORT ClipboardHostImpl
Daniel Cheng9fb887ff2021-10-01 20:27:3838 : public DocumentService<blink::mojom::ClipboardHost> {
danakjc492bf82020-09-09 20:02:4439 public:
40 ~ClipboardHostImpl() override;
41
42 static void Create(
43 RenderFrameHost* render_frame_host,
44 mojo::PendingReceiver<blink::mojom::ClipboardHost> receiver);
45
46 protected:
47 // These types and methods are protected for testing.
48
Darwin Huang6195d042021-02-12 22:36:0049 using IsClipboardPasteContentAllowedCallback =
50 RenderFrameHostImpl::IsClipboardPasteContentAllowedCallback;
danakjc492bf82020-09-09 20:02:4451
Roger Tawac6170262022-10-28 23:48:5252 // Represents the underlying type of the argument passed to
53 // IsClipboardPasteContentAllowedCallback without the const& part.
54 using IsClipboardPasteContentAllowedCallbackArgType =
55 absl::optional<std::string>;
56
danakjc492bf82020-09-09 20:02:4457 // Keeps track of a request to see if some clipboard content, identified by
Rakina Zata Amni39d8e7e2022-10-20 18:18:3058 // its sequence number, is allowed to be pasted into the RenderFrameHost
danakjc492bf82020-09-09 20:02:4459 // that owns this clipboard host.
60 //
61 // A request starts in the state incomplete until Complete() is called with
62 // a value. Callbacks can be added to the request before or after it has
63 // completed.
Darwin Huang6195d042021-02-12 22:36:0064 class CONTENT_EXPORT IsPasteContentAllowedRequest {
danakjc492bf82020-09-09 20:02:4465 public:
Darwin Huang6195d042021-02-12 22:36:0066 IsPasteContentAllowedRequest();
67 ~IsPasteContentAllowedRequest();
danakjc492bf82020-09-09 20:02:4468
69 // Adds |callback| to be notified when the request completes. If the
70 // request is already completed |callback| is invoked immediately. Returns
71 // true if a request should be started after adding this callback.
Darwin Huang6195d042021-02-12 22:36:0072 bool AddCallback(IsClipboardPasteContentAllowedCallback callback);
danakjc492bf82020-09-09 20:02:4473
74 // Mark this request as completed with the specified result.
75 // Invoke all callbacks now.
Roger Tawac6170262022-10-28 23:48:5276 void Complete(IsClipboardPasteContentAllowedCallbackArgType data);
danakjc492bf82020-09-09 20:02:4477
78 // Returns true if this request is obsolete. An obsolete request
79 // is one that is completed, all registered callbacks have been
80 // called, and is considered old.
81 //
82 // |now| represents the current time. It is an argument to ease testing.
83 bool IsObsolete(base::Time now);
84
85 // Returns the time at which this request was created.
86 base::Time time() { return time_; }
87
88 private:
89 // Calls all the callbacks in |callbacks_| with the current value of
90 // |allowed_|. |allowed_| must not be empty.
91 void InvokeCallbacks();
92
93 base::Time time_{base::Time::Now()};
Roger Tawac6170262022-10-28 23:48:5294
95 // The data argument to pass to the IsClipboardPasteContentAllowedCallback.
96 // This member is null until Complete() is called.
97 absl::optional<IsClipboardPasteContentAllowedCallbackArgType> data_;
Darwin Huang6195d042021-02-12 22:36:0098 std::vector<IsClipboardPasteContentAllowedCallback> callbacks_;
danakjc492bf82020-09-09 20:02:4499 };
100
101 // A paste allowed request is obsolete if it is older than this time.
Darwin Huang6195d042021-02-12 22:36:00102 static const base::TimeDelta kIsPasteContentAllowedRequestTooOld;
danakjc492bf82020-09-09 20:02:44103
Alexander Timine3383d02021-06-24 19:57:59104 explicit ClipboardHostImpl(
danakjc70aec1f2022-07-07 15:48:19105 RenderFrameHost& render_frame_host,
Alexander Timine3383d02021-06-24 19:57:59106 mojo::PendingReceiver<blink::mojom::ClipboardHost> receiver);
danakjc492bf82020-09-09 20:02:44107
Aya ElAttar84e6ef32021-03-02 16:29:19108 // Performs a check to see if pasting `data` is allowed by data transfer
109 // policies and invokes PasteIfPolicyAllowedCallback upon completion.
Ana SollanoKim2ae25892022-08-16 19:06:05110 // PerformPasteIfContentAllowed may be invoked immediately if the policy
Aya ElAttar84e6ef32021-03-02 16:29:19111 // controller doesn't exist.
112 void PasteIfPolicyAllowed(ui::ClipboardBuffer clipboard_buffer,
113 const ui::ClipboardFormatType& data_type,
114 std::string data,
115 IsClipboardPasteContentAllowedCallback callback);
116
danakjc492bf82020-09-09 20:02:44117 // Performs a check to see if pasting |data| is allowed and invokes |callback|
Aya ElAttar84e6ef32021-03-02 16:29:19118 // upon completion. |callback| may be invoked immediately if the data has
119 // already been checked. |data| and |seqno| should corresponds to the same
danakjc492bf82020-09-09 20:02:44120 // clipboard data.
Darwin Huang6195d042021-02-12 22:36:00121 void PerformPasteIfContentAllowed(
Austin Sullivanbfe1af72021-07-20 23:14:14122 const ui::ClipboardSequenceNumberToken& seqno,
Darwin Huang6195d042021-02-12 22:36:00123 const ui::ClipboardFormatType& data_type,
124 std::string data,
125 IsClipboardPasteContentAllowedCallback callback);
danakjc492bf82020-09-09 20:02:44126
127 // Remove obsolete entries from the outstanding requests map.
128 // A request is obsolete if:
129 // - its sequence number is less than |seqno|
130 // - it has no callbacks
131 // - it is too old
132 void CleanupObsoleteRequests();
133
Aya ElAttar84e6ef32021-03-02 16:29:19134 // Completion callback of PerformPasteIfContentAllowed(). Sets the allowed
danakjc492bf82020-09-09 20:02:44135 // status for the clipboard data corresponding to sequence number |seqno|.
Austin Sullivanbfe1af72021-07-20 23:14:14136 void FinishPasteIfContentAllowed(
137 const ui::ClipboardSequenceNumberToken& seqno,
Roger Tawac6170262022-10-28 23:48:52138 const absl::optional<std::string>& data);
danakjc492bf82020-09-09 20:02:44139
Austin Sullivanbfe1af72021-07-20 23:14:14140 const std::map<ui::ClipboardSequenceNumberToken,
141 IsPasteContentAllowedRequest>&
danakjc492bf82020-09-09 20:02:44142 is_paste_allowed_requests_for_testing() {
143 return is_allowed_requests_;
144 }
145
146 private:
147 friend class ClipboardHostImplTest;
148 friend class ClipboardHostImplScanTest;
149 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplTest,
Darwin Huang6195d042021-02-12 22:36:00150 IsPasteContentAllowedRequest_AddCallback);
danakjc492bf82020-09-09 20:02:44151 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplTest,
Darwin Huang6195d042021-02-12 22:36:00152 IsPasteContentAllowedRequest_Complete);
danakjc492bf82020-09-09 20:02:44153 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplTest,
Darwin Huang6195d042021-02-12 22:36:00154 IsPasteContentAllowedRequest_IsObsolete);
danakjc492bf82020-09-09 20:02:44155 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplScanTest,
Darwin Huang6195d042021-02-12 22:36:00156 PerformPasteIfContentAllowed_EmptyData);
157 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplScanTest,
158 PerformPasteIfContentAllowed);
danakjc492bf82020-09-09 20:02:44159
160 // mojom::ClipboardHost
161 void GetSequenceNumber(ui::ClipboardBuffer clipboard_buffer,
162 GetSequenceNumberCallback callback) override;
163 void IsFormatAvailable(blink::mojom::ClipboardFormat format,
164 ui::ClipboardBuffer clipboard_buffer,
165 IsFormatAvailableCallback callback) override;
166 void ReadAvailableTypes(ui::ClipboardBuffer clipboard_buffer,
167 ReadAvailableTypesCallback callback) override;
168 void ReadText(ui::ClipboardBuffer clipboard_buffer,
169 ReadTextCallback callback) override;
170 void ReadHtml(ui::ClipboardBuffer clipboard_buffer,
171 ReadHtmlCallback callback) override;
172 void ReadSvg(ui::ClipboardBuffer clipboard_buffer,
173 ReadSvgCallback callback) override;
174 void ReadRtf(ui::ClipboardBuffer clipboard_buffer,
175 ReadRtfCallback callback) override;
Austin Sullivanaa060982021-06-25 17:49:30176 void ReadPng(ui::ClipboardBuffer clipboard_buffer,
177 ReadPngCallback callback) override;
Joel Hockey4c0cb8c2021-02-22 02:59:59178 void ReadFiles(ui::ClipboardBuffer clipboard_buffer,
179 ReadFilesCallback callback) override;
danakjc492bf82020-09-09 20:02:44180 void ReadCustomData(ui::ClipboardBuffer clipboard_buffer,
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58181 const std::u16string& type,
danakjc492bf82020-09-09 20:02:44182 ReadCustomDataCallback callback) override;
Anupam Snigdha74b68e42021-08-10 23:35:59183 void ReadAvailableCustomAndStandardFormats(
184 ReadAvailableCustomAndStandardFormatsCallback callback) override;
185 void ReadUnsanitizedCustomFormat(
186 const std::u16string& format,
187 ReadUnsanitizedCustomFormatCallback callback) override;
188 void WriteUnsanitizedCustomFormat(const std::u16string& format,
189 mojo_base::BigBuffer data) override;
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58190 void WriteText(const std::u16string& text) override;
191 void WriteHtml(const std::u16string& markup, const GURL& url) override;
192 void WriteSvg(const std::u16string& markup) override;
danakjc492bf82020-09-09 20:02:44193 void WriteSmartPasteMarker() override;
194 void WriteCustomData(
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58195 const base::flat_map<std::u16string, std::u16string>& data) override;
danakjc492bf82020-09-09 20:02:44196 void WriteBookmark(const std::string& url,
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58197 const std::u16string& title) override;
danakjbdf1e0a2020-11-10 18:27:47198 void WriteImage(const SkBitmap& unsafe_bitmap) override;
danakjc492bf82020-09-09 20:02:44199 void CommitWrite() override;
Xiaohan Wang7f8052e02022-01-14 18:44:28200#if BUILDFLAG(IS_MAC)
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58201 void WriteStringToFindPboard(const std::u16string& text) override;
danakjc492bf82020-09-09 20:02:44202#endif
203
Anupam Snigdha74b68e42021-08-10 23:35:59204 // Returns true if custom format is allowed to be read/written from/to the
205 // clipboard, else, fails.
206 bool IsUnsanitizedCustomFormatContentAllowed();
207
Darwin Huang6195d042021-02-12 22:36:00208 // Called by PerformPasteIfContentAllowed() when an is allowed request is
209 // needed. Virtual to be overridden in tests.
210 virtual void StartIsPasteContentAllowedRequest(
Austin Sullivanbfe1af72021-07-20 23:14:14211 const ui::ClipboardSequenceNumberToken& seqno,
danakjc492bf82020-09-09 20:02:44212 const ui::ClipboardFormatType& data_type,
213 std::string data);
214
Aya ElAttar84e6ef32021-03-02 16:29:19215 // Completion callback of PasteIfPolicyAllowed. If `is_allowed` is set to
216 // true, PerformPasteIfContentAllowed will be invoked. Otherwise `callback`
217 // will be invoked immediately to cancel the paste.
218 void PasteIfPolicyAllowedCallback(
219 ui::ClipboardBuffer clipboard_buffer,
220 const ui::ClipboardFormatType& data_type,
221 std::string data,
222 IsClipboardPasteContentAllowedCallback callback,
223 bool is_allowed);
224
Anthony Vallee-Duboisac847702021-12-06 21:00:48225 using CopyAllowedCallback = base::OnceCallback<void()>;
226 void CopyIfAllowed(size_t data_size_in_bytes, CopyAllowedCallback callback);
227
Austin Sullivanfc870892021-04-29 18:40:11228 void OnReadPng(ui::ClipboardBuffer clipboard_buffer,
229 ReadPngCallback callback,
230 const std::vector<uint8_t>& data);
danakjc492bf82020-09-09 20:02:44231
Aya ElAttar5e8cfb082020-10-28 14:33:18232 std::unique_ptr<ui::DataTransferEndpoint> CreateDataEndpoint();
danakjc492bf82020-09-09 20:02:44233
danakjc492bf82020-09-09 20:02:44234 std::unique_ptr<ui::ScopedClipboardWriter> clipboard_writer_;
235
236 // Outstanding is allowed requests per clipboard contents. Maps a clipboard
237 // sequence number to an outstanding request.
Austin Sullivanbfe1af72021-07-20 23:14:14238 std::map<ui::ClipboardSequenceNumberToken, IsPasteContentAllowedRequest>
239 is_allowed_requests_;
danakjc492bf82020-09-09 20:02:44240
241 base::WeakPtrFactory<ClipboardHostImpl> weak_ptr_factory_{this};
242};
243
244} // namespace content
245
246#endif // CONTENT_BROWSER_RENDERER_HOST_CLIPBOARD_HOST_IMPL_H_