blob: 77a4ae02af48410d070672a571a50af355f4ea42 [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"
16#include "base/optional.h"
17#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"
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"
23#include "third_party/blink/public/mojom/clipboard/clipboard.mojom.h"
24#include "ui/base/clipboard/clipboard.h"
25
26class GURL;
27
28namespace ui {
29class ScopedClipboardWriter;
30} // namespace ui
31
32namespace content {
33
34class ClipboardHostImplTest;
35
36class CONTENT_EXPORT ClipboardHostImpl : public blink::mojom::ClipboardHost {
37 public:
38 ~ClipboardHostImpl() override;
39
40 static void Create(
41 RenderFrameHost* render_frame_host,
42 mojo::PendingReceiver<blink::mojom::ClipboardHost> receiver);
43
44 protected:
45 // These types and methods are protected for testing.
46
Darwin Huang6195d042021-02-12 22:36:0047 using ClipboardPasteContentAllowed =
48 RenderFrameHostImpl::ClipboardPasteContentAllowed;
49 using IsClipboardPasteContentAllowedCallback =
50 RenderFrameHostImpl::IsClipboardPasteContentAllowedCallback;
danakjc492bf82020-09-09 20:02:4451
52 // Keeps track of a request to see if some clipboard content, identified by
53 // its sequence number, is allowed to be pasted into the render frame host
54 // that owns this clipboard host.
55 //
56 // A request starts in the state incomplete until Complete() is called with
57 // a value. Callbacks can be added to the request before or after it has
58 // completed.
Darwin Huang6195d042021-02-12 22:36:0059 class CONTENT_EXPORT IsPasteContentAllowedRequest {
danakjc492bf82020-09-09 20:02:4460 public:
Darwin Huang6195d042021-02-12 22:36:0061 IsPasteContentAllowedRequest();
62 ~IsPasteContentAllowedRequest();
danakjc492bf82020-09-09 20:02:4463
64 // Adds |callback| to be notified when the request completes. If the
65 // request is already completed |callback| is invoked immediately. Returns
66 // true if a request should be started after adding this callback.
Darwin Huang6195d042021-02-12 22:36:0067 bool AddCallback(IsClipboardPasteContentAllowedCallback callback);
danakjc492bf82020-09-09 20:02:4468
69 // Mark this request as completed with the specified result.
70 // Invoke all callbacks now.
Darwin Huang6195d042021-02-12 22:36:0071 void Complete(ClipboardPasteContentAllowed allowed);
danakjc492bf82020-09-09 20:02:4472
73 // Returns true if this request is obsolete. An obsolete request
74 // is one that is completed, all registered callbacks have been
75 // called, and is considered old.
76 //
77 // |now| represents the current time. It is an argument to ease testing.
78 bool IsObsolete(base::Time now);
79
80 // Returns the time at which this request was created.
81 base::Time time() { return time_; }
82
83 private:
84 // Calls all the callbacks in |callbacks_| with the current value of
85 // |allowed_|. |allowed_| must not be empty.
86 void InvokeCallbacks();
87
88 base::Time time_{base::Time::Now()};
Darwin Huang6195d042021-02-12 22:36:0089 base::Optional<ClipboardPasteContentAllowed> allowed_;
90 std::vector<IsClipboardPasteContentAllowedCallback> callbacks_;
danakjc492bf82020-09-09 20:02:4491 };
92
93 // A paste allowed request is obsolete if it is older than this time.
Darwin Huang6195d042021-02-12 22:36:0094 static const base::TimeDelta kIsPasteContentAllowedRequestTooOld;
danakjc492bf82020-09-09 20:02:4495
Daniel Cheng6f7e1c22021-02-02 05:47:5496 explicit ClipboardHostImpl(RenderFrameHost* render_frame_host);
danakjc492bf82020-09-09 20:02:4497
Aya ElAttar84e6ef32021-03-02 16:29:1998 // Performs a check to see if pasting `data` is allowed by data transfer
99 // policies and invokes PasteIfPolicyAllowedCallback upon completion.
100 // PerformPasteIfContentAllowed maybe be invoked immediately if the policy
101 // controller doesn't exist.
102 void PasteIfPolicyAllowed(ui::ClipboardBuffer clipboard_buffer,
103 const ui::ClipboardFormatType& data_type,
104 std::string data,
105 IsClipboardPasteContentAllowedCallback callback);
106
danakjc492bf82020-09-09 20:02:44107 // Performs a check to see if pasting |data| is allowed and invokes |callback|
Aya ElAttar84e6ef32021-03-02 16:29:19108 // upon completion. |callback| may be invoked immediately if the data has
109 // already been checked. |data| and |seqno| should corresponds to the same
danakjc492bf82020-09-09 20:02:44110 // clipboard data.
Darwin Huang6195d042021-02-12 22:36:00111 void PerformPasteIfContentAllowed(
112 uint64_t seqno,
113 const ui::ClipboardFormatType& data_type,
114 std::string data,
115 IsClipboardPasteContentAllowedCallback callback);
danakjc492bf82020-09-09 20:02:44116
117 // Remove obsolete entries from the outstanding requests map.
118 // A request is obsolete if:
119 // - its sequence number is less than |seqno|
120 // - it has no callbacks
121 // - it is too old
122 void CleanupObsoleteRequests();
123
Aya ElAttar84e6ef32021-03-02 16:29:19124 // Completion callback of PerformPasteIfContentAllowed(). Sets the allowed
danakjc492bf82020-09-09 20:02:44125 // status for the clipboard data corresponding to sequence number |seqno|.
Darwin Huang6195d042021-02-12 22:36:00126 void FinishPasteIfContentAllowed(uint64_t seqno,
127 ClipboardPasteContentAllowed allowed);
danakjc492bf82020-09-09 20:02:44128
Darwin Huang6195d042021-02-12 22:36:00129 const std::map<uint64_t, IsPasteContentAllowedRequest>&
danakjc492bf82020-09-09 20:02:44130 is_paste_allowed_requests_for_testing() {
131 return is_allowed_requests_;
132 }
133
134 private:
135 friend class ClipboardHostImplTest;
136 friend class ClipboardHostImplScanTest;
137 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplTest,
Darwin Huang6195d042021-02-12 22:36:00138 IsPasteContentAllowedRequest_AddCallback);
danakjc492bf82020-09-09 20:02:44139 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplTest,
Darwin Huang6195d042021-02-12 22:36:00140 IsPasteContentAllowedRequest_Complete);
danakjc492bf82020-09-09 20:02:44141 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplTest,
Darwin Huang6195d042021-02-12 22:36:00142 IsPasteContentAllowedRequest_IsObsolete);
danakjc492bf82020-09-09 20:02:44143 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplScanTest,
Darwin Huang6195d042021-02-12 22:36:00144 PerformPasteIfContentAllowed_EmptyData);
145 FRIEND_TEST_ALL_PREFIXES(ClipboardHostImplScanTest,
146 PerformPasteIfContentAllowed);
danakjc492bf82020-09-09 20:02:44147
Austin Sullivanfc870892021-04-29 18:40:11148 // TODO(crbug.com/1201018): Integrate this with mojo.
149 using ReadPngCallback = base::OnceCallback<void(mojo_base::BigBuffer)>;
150
danakjc492bf82020-09-09 20:02:44151 // mojom::ClipboardHost
152 void GetSequenceNumber(ui::ClipboardBuffer clipboard_buffer,
153 GetSequenceNumberCallback callback) override;
154 void IsFormatAvailable(blink::mojom::ClipboardFormat format,
155 ui::ClipboardBuffer clipboard_buffer,
156 IsFormatAvailableCallback callback) override;
157 void ReadAvailableTypes(ui::ClipboardBuffer clipboard_buffer,
158 ReadAvailableTypesCallback callback) override;
159 void ReadText(ui::ClipboardBuffer clipboard_buffer,
160 ReadTextCallback callback) override;
161 void ReadHtml(ui::ClipboardBuffer clipboard_buffer,
162 ReadHtmlCallback callback) override;
163 void ReadSvg(ui::ClipboardBuffer clipboard_buffer,
164 ReadSvgCallback callback) override;
165 void ReadRtf(ui::ClipboardBuffer clipboard_buffer,
166 ReadRtfCallback callback) override;
Austin Sullivanfc870892021-04-29 18:40:11167 void ReadPng(ui::ClipboardBuffer clipboard_buffer, ReadPngCallback callback);
danakjc492bf82020-09-09 20:02:44168 void ReadImage(ui::ClipboardBuffer clipboard_buffer,
169 ReadImageCallback callback) override;
Joel Hockey4c0cb8c2021-02-22 02:59:59170 void ReadFiles(ui::ClipboardBuffer clipboard_buffer,
171 ReadFilesCallback callback) override;
danakjc492bf82020-09-09 20:02:44172 void ReadCustomData(ui::ClipboardBuffer clipboard_buffer,
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58173 const std::u16string& type,
danakjc492bf82020-09-09 20:02:44174 ReadCustomDataCallback callback) override;
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58175 void WriteText(const std::u16string& text) override;
176 void WriteHtml(const std::u16string& markup, const GURL& url) override;
177 void WriteSvg(const std::u16string& markup) override;
danakjc492bf82020-09-09 20:02:44178 void WriteSmartPasteMarker() override;
179 void WriteCustomData(
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58180 const base::flat_map<std::u16string, std::u16string>& data) override;
danakjc492bf82020-09-09 20:02:44181 void WriteBookmark(const std::string& url,
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58182 const std::u16string& title) override;
danakjbdf1e0a2020-11-10 18:27:47183 void WriteImage(const SkBitmap& unsafe_bitmap) override;
danakjc492bf82020-09-09 20:02:44184 void CommitWrite() override;
185#if defined(OS_MAC)
Jan Wilken Dörrieaace0cfef2021-03-11 22:01:58186 void WriteStringToFindPboard(const std::u16string& text) override;
danakjc492bf82020-09-09 20:02:44187#endif
188
Darwin Huang6195d042021-02-12 22:36:00189 // Called by PerformPasteIfContentAllowed() when an is allowed request is
190 // needed. Virtual to be overridden in tests.
191 virtual void StartIsPasteContentAllowedRequest(
danakjc492bf82020-09-09 20:02:44192 uint64_t seqno,
193 const ui::ClipboardFormatType& data_type,
194 std::string data);
195
Aya ElAttar84e6ef32021-03-02 16:29:19196 // Completion callback of PasteIfPolicyAllowed. If `is_allowed` is set to
197 // true, PerformPasteIfContentAllowed will be invoked. Otherwise `callback`
198 // will be invoked immediately to cancel the paste.
199 void PasteIfPolicyAllowedCallback(
200 ui::ClipboardBuffer clipboard_buffer,
201 const ui::ClipboardFormatType& data_type,
202 std::string data,
203 IsClipboardPasteContentAllowedCallback callback,
204 bool is_allowed);
205
Austin Sullivanfc870892021-04-29 18:40:11206 void OnReadPng(ui::ClipboardBuffer clipboard_buffer,
207 ReadPngCallback callback,
208 const std::vector<uint8_t>& data);
danakjc492bf82020-09-09 20:02:44209 void OnReadImage(ui::ClipboardBuffer clipboard_buffer,
210 ReadImageCallback callback,
211 const SkBitmap& bitmap);
212
Aya ElAttar5e8cfb082020-10-28 14:33:18213 std::unique_ptr<ui::DataTransferEndpoint> CreateDataEndpoint();
danakjc492bf82020-09-09 20:02:44214
danakjc492bf82020-09-09 20:02:44215 ui::Clipboard* const clipboard_; // Not owned
Darwin Huang7dadbe812020-10-02 01:06:33216 GlobalFrameRoutingId render_frame_routing_id_;
danakjc492bf82020-09-09 20:02:44217 std::unique_ptr<ui::ScopedClipboardWriter> clipboard_writer_;
218
219 // Outstanding is allowed requests per clipboard contents. Maps a clipboard
220 // sequence number to an outstanding request.
Darwin Huang6195d042021-02-12 22:36:00221 std::map<uint64_t, IsPasteContentAllowedRequest> is_allowed_requests_;
danakjc492bf82020-09-09 20:02:44222
223 base::WeakPtrFactory<ClipboardHostImpl> weak_ptr_factory_{this};
224};
225
226} // namespace content
227
228#endif // CONTENT_BROWSER_RENDERER_HOST_CLIPBOARD_HOST_IMPL_H_