blob: 8205fe2eb4ca4a99e16ff3a7618d185725ef2e1c [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
Roger Tawa34dd57f82022-12-15 23:24:2078 // Returns true if the request has completed.
79 bool is_complete() const { return data_.has_value(); }
80
danakjc492bf82020-09-09 20:02:4481 // Returns true if this request is obsolete. An obsolete request
82 // is one that is completed, all registered callbacks have been
83 // called, and is considered old.
84 //
85 // |now| represents the current time. It is an argument to ease testing.
86 bool IsObsolete(base::Time now);
87
Roger Tawa34dd57f82022-12-15 23:24:2088 // Returns the time at which this request was completed. If called
89 // before the request is completed the return value is undefined.
90 base::Time completed_time();
danakjc492bf82020-09-09 20:02:4491
92 private:
93 // Calls all the callbacks in |callbacks_| with the current value of
94 // |allowed_|. |allowed_| must not be empty.
95 void InvokeCallbacks();
96
Roger Tawa34dd57f82022-12-15 23:24:2097 // The time at which the request was completed. Before completion this
98 // value is undefined.
99 base::Time completed_time_;
Roger Tawac6170262022-10-28 23:48:52100
101 // The data argument to pass to the IsClipboardPasteContentAllowedCallback.
102 // This member is null until Complete() is called.
103 absl::optional<IsClipboardPasteContentAllowedCallbackArgType> data_;
Darwin Huang6195d042021-02-12 22:36:00104 std::vector<IsClipboardPasteContentAllowedCallback> callbacks_;
danakjc492bf82020-09-09 20:02:44105 };
106
107 // A paste allowed request is obsolete if it is older than this time.
Darwin Huang6195d042021-02-12 22:36:00108 static const base::TimeDelta kIsPasteContentAllowedRequestTooOld;
danakjc492bf82020-09-09 20:02:44109
Alexander Timine3383d02021-06-24 19:57:59110 explicit ClipboardHostImpl(
danakjc70aec1f2022-07-07 15:48:19111 RenderFrameHost& render_frame_host,
Alexander Timine3383d02021-06-24 19:57:59112 mojo::PendingReceiver<blink::mojom::ClipboardHost> receiver);
danakjc492bf82020-09-09 20:02:44113
Aya ElAttar84e6ef32021-03-02 16:29:19114 // Performs a check to see if pasting `data` is allowed by data transfer
115 // policies and invokes PasteIfPolicyAllowedCallback upon completion.
Ana SollanoKim2ae25892022-08-16 19:06:05116 // PerformPasteIfContentAllowed may be invoked immediately if the policy
Aya ElAttar84e6ef32021-03-02 16:29:19117 // controller doesn't exist.
118 void PasteIfPolicyAllowed(ui::ClipboardBuffer clipboard_buffer,
119 const ui::ClipboardFormatType& data_type,
120 std::string data,
121 IsClipboardPasteContentAllowedCallback callback);
122
danakjc492bf82020-09-09 20:02:44123 // Performs a check to see if pasting |data| is allowed and invokes |callback|
Aya ElAttar84e6ef32021-03-02 16:29:19124 // upon completion. |callback| may be invoked immediately if the data has
125 // already been checked. |data| and |seqno| should corresponds to the same
danakjc492bf82020-09-09 20:02:44126 // clipboard data.
Darwin Huang6195d042021-02-12 22:36:00127 void PerformPasteIfContentAllowed(
Austin Sullivanbfe1af72021-07-20 23:14:14128 const ui::ClipboardSequenceNumberToken& seqno,
Darwin Huang6195d042021-02-12 22:36:00129 const ui::ClipboardFormatType& data_type,
130 std::string data,
131 IsClipboardPasteContentAllowedCallback callback);
danakjc492bf82020-09-09 20:02:44132
133 // Remove obsolete entries from the outstanding requests map.
134 // A request is obsolete if:
135 // - its sequence number is less than |seqno|
136 // - it has no callbacks
137 // - it is too old
138 void CleanupObsoleteRequests();
139
Aya ElAttar84e6ef32021-03-02 16:29:19140 // Completion callback of PerformPasteIfContentAllowed(). Sets the allowed
danakjc492bf82020-09-09 20:02:44141 // status for the clipboard data corresponding to sequence number |seqno|.
Austin Sullivanbfe1af72021-07-20 23:14:14142 void FinishPasteIfContentAllowed(
143 const ui::ClipboardSequenceNumberToken& seqno,
Roger Tawac6170262022-10-28 23:48:52144 const absl::optional<std::string>& data);
danakjc492bf82020-09-09 20:02:44145
Austin Sullivanbfe1af72021-07-20 23:14:14146 const std::map<ui::ClipboardSequenceNumberToken,
147 IsPasteContentAllowedRequest>&
danakjc492bf82020-09-09 20:02:44148 is_paste_allowed_requests_for_testing() {
149 return is_allowed_requests_;
150 }
151
152 private:
153 friend class ClipboardHostImplTest;
154 friend class ClipboardHostImplScanTest;
155 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplTest,
Darwin Huang6195d042021-02-12 22:36:00156 IsPasteContentAllowedRequest_AddCallback);
danakjc492bf82020-09-09 20:02:44157 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplTest,
Darwin Huang6195d042021-02-12 22:36:00158 IsPasteContentAllowedRequest_Complete);
danakjc492bf82020-09-09 20:02:44159 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplTest,
Darwin Huang6195d042021-02-12 22:36:00160 IsPasteContentAllowedRequest_IsObsolete);
danakjc492bf82020-09-09 20:02:44161 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplScanTest,
Darwin Huang6195d042021-02-12 22:36:00162 PerformPasteIfContentAllowed_EmptyData);
163 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplScanTest,
164 PerformPasteIfContentAllowed);
danakjc492bf82020-09-09 20:02:44165
166 // mojom::ClipboardHost
167 void GetSequenceNumber(ui::ClipboardBuffer clipboard_buffer,
168 GetSequenceNumberCallback callback) override;
169 void IsFormatAvailable(blink::mojom::ClipboardFormat format,
170 ui::ClipboardBuffer clipboard_buffer,
171 IsFormatAvailableCallback callback) override;
172 void ReadAvailableTypes(ui::ClipboardBuffer clipboard_buffer,
173 ReadAvailableTypesCallback callback) override;
174 void ReadText(ui::ClipboardBuffer clipboard_buffer,
175 ReadTextCallback callback) override;
176 void ReadHtml(ui::ClipboardBuffer clipboard_buffer,
177 ReadHtmlCallback callback) override;
178 void ReadSvg(ui::ClipboardBuffer clipboard_buffer,
179 ReadSvgCallback callback) override;
180 void ReadRtf(ui::ClipboardBuffer clipboard_buffer,
181 ReadRtfCallback callback) override;
Austin Sullivanaa060982021-06-25 17:49:30182 void ReadPng(ui::ClipboardBuffer clipboard_buffer,
183 ReadPngCallback callback) override;
Joel Hockey4c0cb8c2021-02-22 02:59:59184 void ReadFiles(ui::ClipboardBuffer clipboard_buffer,
185 ReadFilesCallback callback) override;
danakjc492bf82020-09-09 20:02:44186 void ReadCustomData(ui::ClipboardBuffer clipboard_buffer,
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58187 const std::u16string& type,
danakjc492bf82020-09-09 20:02:44188 ReadCustomDataCallback callback) override;
Anupam Snigdha74b68e42021-08-10 23:35:59189 void ReadAvailableCustomAndStandardFormats(
190 ReadAvailableCustomAndStandardFormatsCallback callback) override;
191 void ReadUnsanitizedCustomFormat(
192 const std::u16string& format,
193 ReadUnsanitizedCustomFormatCallback callback) override;
194 void WriteUnsanitizedCustomFormat(const std::u16string& format,
195 mojo_base::BigBuffer data) override;
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58196 void WriteText(const std::u16string& text) override;
197 void WriteHtml(const std::u16string& markup, const GURL& url) override;
198 void WriteSvg(const std::u16string& markup) override;
danakjc492bf82020-09-09 20:02:44199 void WriteSmartPasteMarker() override;
200 void WriteCustomData(
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58201 const base::flat_map<std::u16string, std::u16string>& data) override;
danakjc492bf82020-09-09 20:02:44202 void WriteBookmark(const std::string& url,
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58203 const std::u16string& title) override;
danakjbdf1e0a2020-11-10 18:27:47204 void WriteImage(const SkBitmap& unsafe_bitmap) override;
danakjc492bf82020-09-09 20:02:44205 void CommitWrite() override;
Xiaohan Wang7f8052e02022-01-14 18:44:28206#if BUILDFLAG(IS_MAC)
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58207 void WriteStringToFindPboard(const std::u16string& text) override;
danakjc492bf82020-09-09 20:02:44208#endif
209
Roger Tawa34dd57f82022-12-15 23:24:20210 // Checks if the renderer allows pasting. This check is skipped if called
211 // soon after a successful content allowed request.
212 bool IsRendererPasteAllowed(ui::ClipboardBuffer clipboard_buffer,
213 RenderFrameHost& render_frame_host);
214
Anupam Snigdha74b68e42021-08-10 23:35:59215 // Returns true if custom format is allowed to be read/written from/to the
216 // clipboard, else, fails.
217 bool IsUnsanitizedCustomFormatContentAllowed();
218
Darwin Huang6195d042021-02-12 22:36:00219 // Called by PerformPasteIfContentAllowed() when an is allowed request is
220 // needed. Virtual to be overridden in tests.
221 virtual void StartIsPasteContentAllowedRequest(
Austin Sullivanbfe1af72021-07-20 23:14:14222 const ui::ClipboardSequenceNumberToken& seqno,
danakjc492bf82020-09-09 20:02:44223 const ui::ClipboardFormatType& data_type,
224 std::string data);
225
Aya ElAttar84e6ef32021-03-02 16:29:19226 // Completion callback of PasteIfPolicyAllowed. If `is_allowed` is set to
227 // true, PerformPasteIfContentAllowed will be invoked. Otherwise `callback`
228 // will be invoked immediately to cancel the paste.
229 void PasteIfPolicyAllowedCallback(
230 ui::ClipboardBuffer clipboard_buffer,
231 const ui::ClipboardFormatType& data_type,
232 std::string data,
233 IsClipboardPasteContentAllowedCallback callback,
234 bool is_allowed);
235
Anthony Vallee-Duboisac847702021-12-06 21:00:48236 using CopyAllowedCallback = base::OnceCallback<void()>;
237 void CopyIfAllowed(size_t data_size_in_bytes, CopyAllowedCallback callback);
238
Austin Sullivanfc870892021-04-29 18:40:11239 void OnReadPng(ui::ClipboardBuffer clipboard_buffer,
240 ReadPngCallback callback,
241 const std::vector<uint8_t>& data);
danakjc492bf82020-09-09 20:02:44242
Aya ElAttar5e8cfb082020-10-28 14:33:18243 std::unique_ptr<ui::DataTransferEndpoint> CreateDataEndpoint();
danakjc492bf82020-09-09 20:02:44244
danakjc492bf82020-09-09 20:02:44245 std::unique_ptr<ui::ScopedClipboardWriter> clipboard_writer_;
246
247 // Outstanding is allowed requests per clipboard contents. Maps a clipboard
248 // sequence number to an outstanding request.
Austin Sullivanbfe1af72021-07-20 23:14:14249 std::map<ui::ClipboardSequenceNumberToken, IsPasteContentAllowedRequest>
250 is_allowed_requests_;
danakjc492bf82020-09-09 20:02:44251
252 base::WeakPtrFactory<ClipboardHostImpl> weak_ptr_factory_{this};
253};
254
255} // namespace content
256
257#endif // CONTENT_BROWSER_RENDERER_HOST_CLIPBOARD_HOST_IMPL_H_