// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef UI_BASE_CLIPBOARD_CLIPBOARD_H_ #define UI_BASE_CLIPBOARD_CLIPBOARD_H_ #include #include #include #include #include #include "base/callback.h" #include "base/compiler_specific.h" #include "base/component_export.h" #include "base/containers/flat_map.h" #include "base/macros.h" #include "base/no_destructor.h" #include "base/process/process.h" #include "base/strings/string16.h" #include "base/synchronization/lock.h" #include "base/threading/platform_thread.h" #include "base/threading/thread_checker.h" #include "base/time/time.h" #include "build/build_config.h" #include "mojo/public/cpp/base/big_buffer.h" #include "ui/base/clipboard/clipboard_buffer.h" #include "ui/base/clipboard/clipboard_format_type.h" #include "ui/base/data_transfer_policy/data_transfer_endpoint.h" class SkBitmap; namespace ui { class TestClipboard; class ScopedClipboardWriter; class DataTransferEndpoint; // Clipboard: // - reads from and writes to the system clipboard. // - specifies an ordering in which to write types to the clipboard // (see PortableFormat). // - is generalized for all targets/operating systems. // TODO(https://crbug.com/443355): Make all functions asynchronous. // Currently, only ReadImage() is asynchronous, but eventually, we would like // all interfaces to be async. class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) Clipboard : public base::ThreadChecker { public: static bool IsSupportedClipboardBuffer(ClipboardBuffer buffer); // Sets the list of threads that are allowed to access the clipboard. static void SetAllowedThreads( const std::vector& allowed_threads); // Sets the clipboard for the current thread, and take ownership of // |platform_clipboard|. // TODO(huangdarwin): In the past, mus allowed >1 clipboard implementation per // platform. Now that mus is removed, only 1 clipboard implementation exists // per platform. Evaluate whether we can or should remove functions like // SetClipboardForCurrentThread, as only one clipboard should exist now. static void SetClipboardForCurrentThread( std::unique_ptr platform_clipboard); // Returns the clipboard object for the current thread. // // Most implementations will have at most one clipboard which will live on // the main UI thread, but Windows has tricky semantics where there have to // be two clipboards: one that lives on the UI thread and one that lives on // the IO thread. static Clipboard* GetForCurrentThread(); // Removes and transfers ownership of the current thread's clipboard to the // caller. If the clipboard was never initialized, returns nullptr. static std::unique_ptr TakeForCurrentThread(); // Does any work necessary prior to Chrome shutdown for the current thread. // All platforms but Windows have a single clipboard shared accross all // threads. This function is a no-op on Windows. On Desktop Linux, if Chrome // has ownership of the clipboard selection this function transfers the // clipboard selection to the clipboard manager. static void OnPreShutdownForCurrentThread(); // Destroys the clipboard for the current thread. Usually, this will clean up // all clipboards, except on Windows. (Previous code leaks the IO thread // clipboard, so it shouldn't be a problem.) static void DestroyClipboardForCurrentThread(); virtual void OnPreShutdown() = 0; // Returns a sequence number which uniquely identifies clipboard state. // This can be used to version the data on the clipboard and determine // whether it has changed. virtual uint64_t GetSequenceNumber(ClipboardBuffer buffer) const = 0; // Tests whether the clipboard contains a certain format. virtual bool IsFormatAvailable( const ClipboardFormatType& format, ClipboardBuffer buffer, const DataTransferEndpoint* data_dst) const = 0; // Returns whether the clipboard has data that is marked by its originator as // confidential. This is available for opt-in checking by the user of this API // as confidential information, like passwords, might legitimately need to be // manipulated. virtual bool IsMarkedByOriginatorAsConfidential() const; // Mark the data on the clipboard as being confidential. This isn't // implemented for all platforms yet, but this call should be made on every // platform so that when it is implemented on other platforms it is picked up. virtual void MarkAsConfidential(); // Clear the clipboard data. virtual void Clear(ClipboardBuffer buffer) = 0; // TODO(huangdarwin): Refactor ReadAvailableTypes to return |types|. // TODO(huangdarwin): Rename to ReadAvailablePortableFormatNames(). // Includes all sanitized types. // Also, includes pickled types by splitting them out of the pickled format. virtual void ReadAvailableTypes(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, std::vector* types) const = 0; // Includes all types, including unsanitized types. // Omits formats held within pickles, as they're different from what a native // application would see. virtual std::vector ReadAvailablePlatformSpecificFormatNames( ClipboardBuffer buffer, const DataTransferEndpoint* data_dst) const = 0; // Reads Unicode text from the clipboard, if available. virtual void ReadText(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, base::string16* result) const = 0; // Reads ASCII text from the clipboard, if available. virtual void ReadAsciiText(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, std::string* result) const = 0; // Reads HTML from the clipboard, if available. If the HTML fragment requires // context to parse, |fragment_start| and |fragment_end| are indexes into // markup indicating the beginning and end of the actual fragment. Otherwise, // they will contain 0 and markup->size(). virtual void ReadHTML(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, base::string16* markup, std::string* src_url, uint32_t* fragment_start, uint32_t* fragment_end) const = 0; // Reads an SVG image from the clipboard, if available. virtual void ReadSvg(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, base::string16* result) const = 0; // Reads RTF from the clipboard, if available. Stores the result as a byte // vector. virtual void ReadRTF(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, std::string* result) const = 0; using ReadImageCallback = base::OnceCallback; // Reads an image from the clipboard, if available. virtual void ReadImage(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, ReadImageCallback callback) const = 0; virtual void ReadCustomData(ClipboardBuffer buffer, const base::string16& type, const DataTransferEndpoint* data_dst, base::string16* result) const = 0; // Reads a bookmark from the clipboard, if available. // |title| or |url| may be null. virtual void ReadBookmark(const DataTransferEndpoint* data_dst, base::string16* title, std::string* url) const = 0; // Reads raw data from the clipboard with the given format type. Stores result // as a byte vector. virtual void ReadData(const ClipboardFormatType& format, const DataTransferEndpoint* data_dst, std::string* result) const = 0; // Returns an estimate of the time the clipboard was last updated. If the // time is unknown, returns Time::Time(). virtual base::Time GetLastModifiedTime() const; // Resets the clipboard last modified time to Time::Time(). virtual void ClearLastModifiedTime(); protected: // PortableFormat designates the type of data to be stored in the clipboard. // This designation is shared across all OSes. The system-specific designation // is defined by ClipboardFormatType. A single PortableFormat might be // represented by several system-specific ClipboardFormatTypes. For example, // on Linux the kText PortableFormat maps to "text/plain", "STRING", and // several other formats. On windows it maps to CF_UNICODETEXT. // // The order below is the order in which data will be written to the // clipboard, so more specific types must be listed before less specific // types. For example, placing an image on the clipboard might cause the // clipboard to contain a bitmap, HTML markup representing the image, a URL to // the image, and the image's alt text. Having the types follow this order // maximizes the amount of data that can be extracted by various programs. enum class PortableFormat { kBitmap, // Bitmap from shared memory. kHtml, kRtf, kBookmark, kText, kWebkit, kData, // Arbitrary block of bytes. kSvg, }; // TODO (https://crbug.com/994928): Rename ObjectMap-related types. // ObjectMap is a map from PortableFormat to associated data. // The data is organized differently for each PortableFormat. The following // table summarizes what kind of data is stored for each key. // * indicates an optional argument. // // Key Arguments Type // ------------------------------------- // kBitmap bitmap A pointer to a SkBitmap. The caller must ensure // the SkBitmap remains live for the duration of // the WritePortableRepresentations call. // kHtml html char array // url* char array // kRtf data byte array // kBookmark html char array // url char array // kText text char array // kWebkit none empty vector // kData format char array // data byte array using ObjectMapParam = std::vector; using ObjectMapParams = std::vector; using ObjectMap = base::flat_map; // PlatformRepresentation is used for DispatchPlatformRepresentations, and // supports writing directly to the system clipboard, without custom type // mapping per platform. struct PlatformRepresentation { std::string format; // BigBuffer shared memory is still writable from the renderer when backed // by shared memory, so PlatformRepresentation's data.data() must not be // branched on, and *data.data() must not be accessed, except to copy it // into private memory. mojo_base::BigBuffer data; }; static Clipboard* Create(); Clipboard(); virtual ~Clipboard(); // Write a bunch of objects to the system clipboard. Copies are made of the // contents of |objects|. Also, adds the source of the data to the clipboard, // which can be used when we need to restrict the clipboard data between a set // of confidential documents. The data source maybe passed as nullptr. virtual void WritePortableRepresentations( ClipboardBuffer buffer, const ObjectMap& objects, std::unique_ptr data_src) = 0; // Write |platform_representations|, in the order of their appearance in // |platform_representations|. Also, adds the source of the data to the // clipboard, which can be used when we need to restrict the clipboard data // between a set of confidential documents. The data source maybe passed as // nullptr. virtual void WritePlatformRepresentations( ClipboardBuffer buffer, std::vector platform_representations, std::unique_ptr data_src) = 0; void DispatchPortableRepresentation(PortableFormat format, const ObjectMapParams& params); // Write directly to the system clipboard. void DispatchPlatformRepresentations( std::vector platform_representations); virtual void WriteText(const char* text_data, size_t text_len) = 0; virtual void WriteHTML(const char* markup_data, size_t markup_len, const char* url_data, size_t url_len) = 0; virtual void WriteSvg(const char* markup_data, size_t markup_len) = 0; virtual void WriteRTF(const char* rtf_data, size_t data_len) = 0; virtual void WriteBookmark(const char* title_data, size_t title_len, const char* url_data, size_t url_len) = 0; virtual void WriteWebSmartPaste() = 0; virtual void WriteBitmap(const SkBitmap& bitmap) = 0; // |data_data| is shared memory, and is still writable from the renderer. // Therefore, |data_data| must not be branched on, and *|data_data| must not // be accessed, except to copy it into private memory. virtual void WriteData(const ClipboardFormatType& format, const char* data_data, size_t data_len) = 0; private: // For access to WritePortableRepresentations(). friend class ForwardingTestingClipboard; friend class ScopedClipboardWriter; friend class TestClipboard; // For SetClipboardForCurrentThread's argument. friend struct std::default_delete; static base::PlatformThreadId GetAndValidateThreadID(); #if defined(USE_OZONE) // Returns whether the selection buffer is available. This is true for some // Linux platforms. virtual bool IsSelectionBufferAvailable() const = 0; #endif // defined(USE_OZONE) // A list of allowed threads. By default, this is empty and no thread checking // is done (in the unit test case), but a user (like content) can set which // threads are allowed to call this method. static std::vector& AllowedThreads(); // Mapping from threads to clipboard objects. using ClipboardMap = base::flat_map>; static ClipboardMap* ClipboardMapPtr(); // Mutex that controls access to |g_clipboard_map|. static base::Lock& ClipboardMapLock(); DISALLOW_COPY_AND_ASSIGN(Clipboard); }; } // namespace ui #endif // UI_BASE_CLIPBOARD_CLIPBOARD_H_