1 // 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 UI_BASE_CLIPBOARD_CLIPBOARD_H_
6 #define UI_BASE_CLIPBOARD_CLIPBOARD_H_
7
8 #include <stddef.h>
9 #include <stdint.h>
10
11 #include <memory>
12 #include <string>
13 #include <vector>
14
15 #include "base/callback.h"
16 #include "base/compiler_specific.h"
17 #include "base/component_export.h"
18 #include "base/containers/flat_map.h"
19 #include "base/macros.h"
20 #include "base/no_destructor.h"
21 #include "base/process/process.h"
22 #include "base/strings/string16.h"
23 #include "base/synchronization/lock.h"
24 #include "base/threading/platform_thread.h"
25 #include "base/threading/thread_checker.h"
26 #include "base/time/time.h"
27 #include "build/build_config.h"
28 #include "mojo/public/cpp/base/big_buffer.h"
29 #include "ui/base/clipboard/clipboard_buffer.h"
30 #include "ui/base/clipboard/clipboard_format_type.h"
31 #include "ui/base/data_transfer_policy/data_transfer_endpoint.h"
32
33 class SkBitmap;
34
35 namespace ui {
36 class TestClipboard;
37 class ScopedClipboardWriter;
38 class DataTransferEndpoint;
39
40 // Clipboard:
41 // - reads from and writes to the system clipboard.
42 // - specifies an ordering in which to write types to the clipboard
43 // (see PortableFormat).
44 // - is generalized for all targets/operating systems.
45 // TODO(https://crbug.com/443355): Make all functions asynchronous.
46 // Currently, only ReadImage() is asynchronous, but eventually, we would like
47 // all interfaces to be async.
COMPONENT_EXPORT(UI_BASE_CLIPBOARD)48 class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) Clipboard
49 : public base::ThreadChecker {
50 public:
51 static bool IsSupportedClipboardBuffer(ClipboardBuffer buffer);
52
53 // Sets the list of threads that are allowed to access the clipboard.
54 static void SetAllowedThreads(
55 const std::vector<base::PlatformThreadId>& allowed_threads);
56
57 // Sets the clipboard for the current thread, and take ownership of
58 // |platform_clipboard|.
59 // TODO(huangdarwin): In the past, mus allowed >1 clipboard implementation per
60 // platform. Now that mus is removed, only 1 clipboard implementation exists
61 // per platform. Evaluate whether we can or should remove functions like
62 // SetClipboardForCurrentThread, as only one clipboard should exist now.
63 static void SetClipboardForCurrentThread(
64 std::unique_ptr<Clipboard> platform_clipboard);
65
66 // Returns the clipboard object for the current thread.
67 //
68 // Most implementations will have at most one clipboard which will live on
69 // the main UI thread, but Windows has tricky semantics where there have to
70 // be two clipboards: one that lives on the UI thread and one that lives on
71 // the IO thread.
72 static Clipboard* GetForCurrentThread();
73
74 // Removes and transfers ownership of the current thread's clipboard to the
75 // caller. If the clipboard was never initialized, returns nullptr.
76 static std::unique_ptr<Clipboard> TakeForCurrentThread();
77
78 // Does any work necessary prior to Chrome shutdown for the current thread.
79 // All platforms but Windows have a single clipboard shared accross all
80 // threads. This function is a no-op on Windows. On Desktop Linux, if Chrome
81 // has ownership of the clipboard selection this function transfers the
82 // clipboard selection to the clipboard manager.
83 static void OnPreShutdownForCurrentThread();
84
85 // Destroys the clipboard for the current thread. Usually, this will clean up
86 // all clipboards, except on Windows. (Previous code leaks the IO thread
87 // clipboard, so it shouldn't be a problem.)
88 static void DestroyClipboardForCurrentThread();
89
90 virtual void OnPreShutdown() = 0;
91
92 // Returns a sequence number which uniquely identifies clipboard state.
93 // This can be used to version the data on the clipboard and determine
94 // whether it has changed.
95 virtual uint64_t GetSequenceNumber(ClipboardBuffer buffer) const = 0;
96
97 // Tests whether the clipboard contains a certain format.
98 virtual bool IsFormatAvailable(
99 const ClipboardFormatType& format,
100 ClipboardBuffer buffer,
101 const DataTransferEndpoint* data_dst) const = 0;
102
103 // Returns whether the clipboard has data that is marked by its originator as
104 // confidential. This is available for opt-in checking by the user of this API
105 // as confidential information, like passwords, might legitimately need to be
106 // manipulated.
107 virtual bool IsMarkedByOriginatorAsConfidential() const;
108
109 // Mark the data on the clipboard as being confidential. This isn't
110 // implemented for all platforms yet, but this call should be made on every
111 // platform so that when it is implemented on other platforms it is picked up.
112 virtual void MarkAsConfidential();
113
114 // Clear the clipboard data.
115 virtual void Clear(ClipboardBuffer buffer) = 0;
116
117 // TODO(huangdarwin): Refactor ReadAvailableTypes to return |types|.
118 // TODO(huangdarwin): Rename to ReadAvailablePortableFormatNames().
119 // Includes all sanitized types.
120 // Also, includes pickled types by splitting them out of the pickled format.
121 virtual void ReadAvailableTypes(ClipboardBuffer buffer,
122 const DataTransferEndpoint* data_dst,
123 std::vector<base::string16>* types) const = 0;
124 // Includes all types, including unsanitized types.
125 // Omits formats held within pickles, as they're different from what a native
126 // application would see.
127 virtual std::vector<base::string16> ReadAvailablePlatformSpecificFormatNames(
128 ClipboardBuffer buffer,
129 const DataTransferEndpoint* data_dst) const = 0;
130
131 // Reads Unicode text from the clipboard, if available.
132 virtual void ReadText(ClipboardBuffer buffer,
133 const DataTransferEndpoint* data_dst,
134 base::string16* result) const = 0;
135
136 // Reads ASCII text from the clipboard, if available.
137 virtual void ReadAsciiText(ClipboardBuffer buffer,
138 const DataTransferEndpoint* data_dst,
139 std::string* result) const = 0;
140
141 // Reads HTML from the clipboard, if available. If the HTML fragment requires
142 // context to parse, |fragment_start| and |fragment_end| are indexes into
143 // markup indicating the beginning and end of the actual fragment. Otherwise,
144 // they will contain 0 and markup->size().
145 virtual void ReadHTML(ClipboardBuffer buffer,
146 const DataTransferEndpoint* data_dst,
147 base::string16* markup,
148 std::string* src_url,
149 uint32_t* fragment_start,
150 uint32_t* fragment_end) const = 0;
151
152 // Reads an SVG image from the clipboard, if available.
153 virtual void ReadSvg(ClipboardBuffer buffer,
154 const DataTransferEndpoint* data_dst,
155 base::string16* result) const = 0;
156 // Reads RTF from the clipboard, if available. Stores the result as a byte
157 // vector.
158 virtual void ReadRTF(ClipboardBuffer buffer,
159 const DataTransferEndpoint* data_dst,
160 std::string* result) const = 0;
161
162 using ReadImageCallback = base::OnceCallback<void(const SkBitmap&)>;
163
164 // Reads an image from the clipboard, if available.
165 virtual void ReadImage(ClipboardBuffer buffer,
166 const DataTransferEndpoint* data_dst,
167 ReadImageCallback callback) const = 0;
168
169 virtual void ReadCustomData(ClipboardBuffer buffer,
170 const base::string16& type,
171 const DataTransferEndpoint* data_dst,
172 base::string16* result) const = 0;
173
174 // Reads a bookmark from the clipboard, if available.
175 // |title| or |url| may be null.
176 virtual void ReadBookmark(const DataTransferEndpoint* data_dst,
177 base::string16* title,
178 std::string* url) const = 0;
179
180 // Reads raw data from the clipboard with the given format type. Stores result
181 // as a byte vector.
182 virtual void ReadData(const ClipboardFormatType& format,
183 const DataTransferEndpoint* data_dst,
184 std::string* result) const = 0;
185
186 // Returns an estimate of the time the clipboard was last updated. If the
187 // time is unknown, returns Time::Time().
188 virtual base::Time GetLastModifiedTime() const;
189
190 // Resets the clipboard last modified time to Time::Time().
191 virtual void ClearLastModifiedTime();
192
193 protected:
194 // PortableFormat designates the type of data to be stored in the clipboard.
195 // This designation is shared across all OSes. The system-specific designation
196 // is defined by ClipboardFormatType. A single PortableFormat might be
197 // represented by several system-specific ClipboardFormatTypes. For example,
198 // on Linux the kText PortableFormat maps to "text/plain", "STRING", and
199 // several other formats. On windows it maps to CF_UNICODETEXT.
200 //
201 // The order below is the order in which data will be written to the
202 // clipboard, so more specific types must be listed before less specific
203 // types. For example, placing an image on the clipboard might cause the
204 // clipboard to contain a bitmap, HTML markup representing the image, a URL to
205 // the image, and the image's alt text. Having the types follow this order
206 // maximizes the amount of data that can be extracted by various programs.
207 enum class PortableFormat {
208 kBitmap, // Bitmap from shared memory.
209 kHtml,
210 kRtf,
211 kBookmark,
212 kText,
213 kWebkit,
214 kData, // Arbitrary block of bytes.
215 kSvg,
216 };
217
218 // TODO (https://crbug.com/994928): Rename ObjectMap-related types.
219 // ObjectMap is a map from PortableFormat to associated data.
220 // The data is organized differently for each PortableFormat. The following
221 // table summarizes what kind of data is stored for each key.
222 // * indicates an optional argument.
223 //
224 // Key Arguments Type
225 // -------------------------------------
226 // kBitmap bitmap A pointer to a SkBitmap. The caller must ensure
227 // the SkBitmap remains live for the duration of
228 // the WritePortableRepresentations call.
229 // kHtml html char array
230 // url* char array
231 // kRtf data byte array
232 // kBookmark html char array
233 // url char array
234 // kText text char array
235 // kWebkit none empty vector
236 // kData format char array
237 // data byte array
238 using ObjectMapParam = std::vector<char>;
239 using ObjectMapParams = std::vector<ObjectMapParam>;
240 using ObjectMap = base::flat_map<PortableFormat, ObjectMapParams>;
241
242 // PlatformRepresentation is used for DispatchPlatformRepresentations, and
243 // supports writing directly to the system clipboard, without custom type
244 // mapping per platform.
245 struct PlatformRepresentation {
246 std::string format;
247 // BigBuffer shared memory is still writable from the renderer when backed
248 // by shared memory, so PlatformRepresentation's data.data() must not be
249 // branched on, and *data.data() must not be accessed, except to copy it
250 // into private memory.
251 mojo_base::BigBuffer data;
252 };
253
254 static Clipboard* Create();
255
256 Clipboard();
257 virtual ~Clipboard();
258
259 // Write a bunch of objects to the system clipboard. Copies are made of the
260 // contents of |objects|. Also, adds the source of the data to the clipboard,
261 // which can be used when we need to restrict the clipboard data between a set
262 // of confidential documents. The data source maybe passed as nullptr.
263 virtual void WritePortableRepresentations(
264 ClipboardBuffer buffer,
265 const ObjectMap& objects,
266 std::unique_ptr<DataTransferEndpoint> data_src) = 0;
267
268 // Write |platform_representations|, in the order of their appearance in
269 // |platform_representations|. Also, adds the source of the data to the
270 // clipboard, which can be used when we need to restrict the clipboard data
271 // between a set of confidential documents. The data source maybe passed as
272 // nullptr.
273 virtual void WritePlatformRepresentations(
274 ClipboardBuffer buffer,
275 std::vector<Clipboard::PlatformRepresentation> platform_representations,
276 std::unique_ptr<DataTransferEndpoint> data_src) = 0;
277
278 void DispatchPortableRepresentation(PortableFormat format,
279 const ObjectMapParams& params);
280
281 // Write directly to the system clipboard.
282 void DispatchPlatformRepresentations(
283 std::vector<Clipboard::PlatformRepresentation> platform_representations);
284
285 virtual void WriteText(const char* text_data, size_t text_len) = 0;
286
287 virtual void WriteHTML(const char* markup_data,
288 size_t markup_len,
289 const char* url_data,
290 size_t url_len) = 0;
291
292 virtual void WriteSvg(const char* markup_data, size_t markup_len) = 0;
293
294 virtual void WriteRTF(const char* rtf_data, size_t data_len) = 0;
295
296 virtual void WriteBookmark(const char* title_data,
297 size_t title_len,
298 const char* url_data,
299 size_t url_len) = 0;
300
301 virtual void WriteWebSmartPaste() = 0;
302
303 virtual void WriteBitmap(const SkBitmap& bitmap) = 0;
304
305 // |data_data| is shared memory, and is still writable from the renderer.
306 // Therefore, |data_data| must not be branched on, and *|data_data| must not
307 // be accessed, except to copy it into private memory.
308 virtual void WriteData(const ClipboardFormatType& format,
309 const char* data_data,
310 size_t data_len) = 0;
311
312 private:
313 // For access to WritePortableRepresentations().
314 friend class ForwardingTestingClipboard;
315 friend class ScopedClipboardWriter;
316 friend class TestClipboard;
317 // For SetClipboardForCurrentThread's argument.
318 friend struct std::default_delete<Clipboard>;
319
320 static base::PlatformThreadId GetAndValidateThreadID();
321
322 #if defined(USE_OZONE)
323 // Returns whether the selection buffer is available. This is true for some
324 // Linux platforms.
325 virtual bool IsSelectionBufferAvailable() const = 0;
326 #endif // defined(USE_OZONE)
327
328 // A list of allowed threads. By default, this is empty and no thread checking
329 // is done (in the unit test case), but a user (like content) can set which
330 // threads are allowed to call this method.
331 static std::vector<base::PlatformThreadId>& AllowedThreads();
332
333 // Mapping from threads to clipboard objects.
334 using ClipboardMap =
335 base::flat_map<base::PlatformThreadId, std::unique_ptr<Clipboard>>;
336 static ClipboardMap* ClipboardMapPtr();
337
338 // Mutex that controls access to |g_clipboard_map|.
339 static base::Lock& ClipboardMapLock();
340
341 DISALLOW_COPY_AND_ASSIGN(Clipboard);
342 };
343
344 } // namespace ui
345
346 #endif // UI_BASE_CLIPBOARD_CLIPBOARD_H_
347