blob: e920098384ec51f06671f6b09c04a5263644411a [file] [log] [blame]
danakjc492bf82020-09-09 20:02:441// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// 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"
danakjc492bf82020-09-09 20:02:4414#include "base/macros.h"
15#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"
Alexander Timine3383d02021-06-24 19:57:5920#include "content/public/browser/document_service_base.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
38 : public DocumentServiceBase<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 ClipboardPasteContentAllowed =
50 RenderFrameHostImpl::ClipboardPasteContentAllowed;
51 using IsClipboardPasteContentAllowedCallback =
52 RenderFrameHostImpl::IsClipboardPasteContentAllowedCallback;
danakjc492bf82020-09-09 20:02:4453
54 // Keeps track of a request to see if some clipboard content, identified by
55 // its sequence number, is allowed to be pasted into the render frame host
56 // that owns this clipboard host.
57 //
58 // A request starts in the state incomplete until Complete() is called with
59 // a value. Callbacks can be added to the request before or after it has
60 // completed.
Darwin Huang6195d042021-02-12 22:36:0061 class CONTENT_EXPORT IsPasteContentAllowedRequest {
danakjc492bf82020-09-09 20:02:4462 public:
Darwin Huang6195d042021-02-12 22:36:0063 IsPasteContentAllowedRequest();
64 ~IsPasteContentAllowedRequest();
danakjc492bf82020-09-09 20:02:4465
66 // Adds |callback| to be notified when the request completes. If the
67 // request is already completed |callback| is invoked immediately. Returns
68 // true if a request should be started after adding this callback.
Darwin Huang6195d042021-02-12 22:36:0069 bool AddCallback(IsClipboardPasteContentAllowedCallback callback);
danakjc492bf82020-09-09 20:02:4470
71 // Mark this request as completed with the specified result.
72 // Invoke all callbacks now.
Darwin Huang6195d042021-02-12 22:36:0073 void Complete(ClipboardPasteContentAllowed allowed);
danakjc492bf82020-09-09 20:02:4474
75 // Returns true if this request is obsolete. An obsolete request
76 // is one that is completed, all registered callbacks have been
77 // called, and is considered old.
78 //
79 // |now| represents the current time. It is an argument to ease testing.
80 bool IsObsolete(base::Time now);
81
82 // Returns the time at which this request was created.
83 base::Time time() { return time_; }
84
85 private:
86 // Calls all the callbacks in |callbacks_| with the current value of
87 // |allowed_|. |allowed_| must not be empty.
88 void InvokeCallbacks();
89
90 base::Time time_{base::Time::Now()};
Anton Bikineevf62d1bf2021-05-15 17:56:0791 absl::optional<ClipboardPasteContentAllowed> allowed_;
Darwin Huang6195d042021-02-12 22:36:0092 std::vector<IsClipboardPasteContentAllowedCallback> callbacks_;
danakjc492bf82020-09-09 20:02:4493 };
94
95 // A paste allowed request is obsolete if it is older than this time.
Darwin Huang6195d042021-02-12 22:36:0096 static const base::TimeDelta kIsPasteContentAllowedRequestTooOld;
danakjc492bf82020-09-09 20:02:4497
Alexander Timine3383d02021-06-24 19:57:5998 explicit ClipboardHostImpl(
99 RenderFrameHost* render_frame_host,
100 mojo::PendingReceiver<blink::mojom::ClipboardHost> receiver);
danakjc492bf82020-09-09 20:02:44101
Aya ElAttar84e6ef32021-03-02 16:29:19102 // Performs a check to see if pasting `data` is allowed by data transfer
103 // policies and invokes PasteIfPolicyAllowedCallback upon completion.
104 // PerformPasteIfContentAllowed maybe be invoked immediately if the policy
105 // controller doesn't exist.
106 void PasteIfPolicyAllowed(ui::ClipboardBuffer clipboard_buffer,
107 const ui::ClipboardFormatType& data_type,
108 std::string data,
109 IsClipboardPasteContentAllowedCallback callback);
110
danakjc492bf82020-09-09 20:02:44111 // Performs a check to see if pasting |data| is allowed and invokes |callback|
Aya ElAttar84e6ef32021-03-02 16:29:19112 // upon completion. |callback| may be invoked immediately if the data has
113 // already been checked. |data| and |seqno| should corresponds to the same
danakjc492bf82020-09-09 20:02:44114 // clipboard data.
Darwin Huang6195d042021-02-12 22:36:00115 void PerformPasteIfContentAllowed(
Austin Sullivanbfe1af72021-07-20 23:14:14116 const ui::ClipboardSequenceNumberToken& seqno,
Darwin Huang6195d042021-02-12 22:36:00117 const ui::ClipboardFormatType& data_type,
118 std::string data,
119 IsClipboardPasteContentAllowedCallback callback);
danakjc492bf82020-09-09 20:02:44120
121 // Remove obsolete entries from the outstanding requests map.
122 // A request is obsolete if:
123 // - its sequence number is less than |seqno|
124 // - it has no callbacks
125 // - it is too old
126 void CleanupObsoleteRequests();
127
Aya ElAttar84e6ef32021-03-02 16:29:19128 // Completion callback of PerformPasteIfContentAllowed(). Sets the allowed
danakjc492bf82020-09-09 20:02:44129 // status for the clipboard data corresponding to sequence number |seqno|.
Austin Sullivanbfe1af72021-07-20 23:14:14130 void FinishPasteIfContentAllowed(
131 const ui::ClipboardSequenceNumberToken& seqno,
132 ClipboardPasteContentAllowed allowed);
danakjc492bf82020-09-09 20:02:44133
Austin Sullivanbfe1af72021-07-20 23:14:14134 const std::map<ui::ClipboardSequenceNumberToken,
135 IsPasteContentAllowedRequest>&
danakjc492bf82020-09-09 20:02:44136 is_paste_allowed_requests_for_testing() {
137 return is_allowed_requests_;
138 }
139
140 private:
141 friend class ClipboardHostImplTest;
142 friend class ClipboardHostImplScanTest;
143 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplTest,
Darwin Huang6195d042021-02-12 22:36:00144 IsPasteContentAllowedRequest_AddCallback);
danakjc492bf82020-09-09 20:02:44145 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplTest,
Darwin Huang6195d042021-02-12 22:36:00146 IsPasteContentAllowedRequest_Complete);
danakjc492bf82020-09-09 20:02:44147 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplTest,
Darwin Huang6195d042021-02-12 22:36:00148 IsPasteContentAllowedRequest_IsObsolete);
danakjc492bf82020-09-09 20:02:44149 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplScanTest,
Darwin Huang6195d042021-02-12 22:36:00150 PerformPasteIfContentAllowed_EmptyData);
151 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplScanTest,
152 PerformPasteIfContentAllowed);
danakjc492bf82020-09-09 20:02:44153
154 // mojom::ClipboardHost
155 void GetSequenceNumber(ui::ClipboardBuffer clipboard_buffer,
156 GetSequenceNumberCallback callback) override;
157 void IsFormatAvailable(blink::mojom::ClipboardFormat format,
158 ui::ClipboardBuffer clipboard_buffer,
159 IsFormatAvailableCallback callback) override;
160 void ReadAvailableTypes(ui::ClipboardBuffer clipboard_buffer,
161 ReadAvailableTypesCallback callback) override;
162 void ReadText(ui::ClipboardBuffer clipboard_buffer,
163 ReadTextCallback callback) override;
164 void ReadHtml(ui::ClipboardBuffer clipboard_buffer,
165 ReadHtmlCallback callback) override;
166 void ReadSvg(ui::ClipboardBuffer clipboard_buffer,
167 ReadSvgCallback callback) override;
168 void ReadRtf(ui::ClipboardBuffer clipboard_buffer,
169 ReadRtfCallback callback) override;
Austin Sullivanaa060982021-06-25 17:49:30170 void ReadPng(ui::ClipboardBuffer clipboard_buffer,
171 ReadPngCallback callback) override;
danakjc492bf82020-09-09 20:02:44172 void ReadImage(ui::ClipboardBuffer clipboard_buffer,
173 ReadImageCallback callback) override;
Joel Hockey4c0cb8c2021-02-22 02:59:59174 void ReadFiles(ui::ClipboardBuffer clipboard_buffer,
175 ReadFilesCallback callback) override;
danakjc492bf82020-09-09 20:02:44176 void ReadCustomData(ui::ClipboardBuffer clipboard_buffer,
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58177 const std::u16string& type,
danakjc492bf82020-09-09 20:02:44178 ReadCustomDataCallback callback) override;
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58179 void WriteText(const std::u16string& text) override;
180 void WriteHtml(const std::u16string& markup, const GURL& url) override;
181 void WriteSvg(const std::u16string& markup) override;
danakjc492bf82020-09-09 20:02:44182 void WriteSmartPasteMarker() override;
183 void WriteCustomData(
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58184 const base::flat_map<std::u16string, std::u16string>& data) override;
danakjc492bf82020-09-09 20:02:44185 void WriteBookmark(const std::string& url,
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58186 const std::u16string& title) override;
danakjbdf1e0a2020-11-10 18:27:47187 void WriteImage(const SkBitmap& unsafe_bitmap) override;
danakjc492bf82020-09-09 20:02:44188 void CommitWrite() override;
189#if defined(OS_MAC)
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58190 void WriteStringToFindPboard(const std::u16string& text) override;
danakjc492bf82020-09-09 20:02:44191#endif
192
Darwin Huang6195d042021-02-12 22:36:00193 // Called by PerformPasteIfContentAllowed() when an is allowed request is
194 // needed. Virtual to be overridden in tests.
195 virtual void StartIsPasteContentAllowedRequest(
Austin Sullivanbfe1af72021-07-20 23:14:14196 const ui::ClipboardSequenceNumberToken& seqno,
danakjc492bf82020-09-09 20:02:44197 const ui::ClipboardFormatType& data_type,
198 std::string data);
199
Aya ElAttar84e6ef32021-03-02 16:29:19200 // Completion callback of PasteIfPolicyAllowed. If `is_allowed` is set to
201 // true, PerformPasteIfContentAllowed will be invoked. Otherwise `callback`
202 // will be invoked immediately to cancel the paste.
203 void PasteIfPolicyAllowedCallback(
204 ui::ClipboardBuffer clipboard_buffer,
205 const ui::ClipboardFormatType& data_type,
206 std::string data,
207 IsClipboardPasteContentAllowedCallback callback,
208 bool is_allowed);
209
Austin Sullivanfc870892021-04-29 18:40:11210 void OnReadPng(ui::ClipboardBuffer clipboard_buffer,
211 ReadPngCallback callback,
212 const std::vector<uint8_t>& data);
danakjc492bf82020-09-09 20:02:44213 void OnReadImage(ui::ClipboardBuffer clipboard_buffer,
214 ReadImageCallback callback,
215 const SkBitmap& bitmap);
216
Aya ElAttar5e8cfb082020-10-28 14:33:18217 std::unique_ptr<ui::DataTransferEndpoint> CreateDataEndpoint();
danakjc492bf82020-09-09 20:02:44218
danakjc492bf82020-09-09 20:02:44219 std::unique_ptr<ui::ScopedClipboardWriter> clipboard_writer_;
220
221 // Outstanding is allowed requests per clipboard contents. Maps a clipboard
222 // sequence number to an outstanding request.
Austin Sullivanbfe1af72021-07-20 23:14:14223 std::map<ui::ClipboardSequenceNumberToken, IsPasteContentAllowedRequest>
224 is_allowed_requests_;
danakjc492bf82020-09-09 20:02:44225
226 base::WeakPtrFactory<ClipboardHostImpl> weak_ptr_factory_{this};
227};
228
229} // namespace content
230
231#endif // CONTENT_BROWSER_RENDERER_HOST_CLIPBOARD_HOST_IMPL_H_