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