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 #include "ui/base/clipboard/scoped_clipboard_writer.h"
6 
7 #include "base/pickle.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "net/base/escape.h"
10 #include "ui/base/clipboard/clipboard_format_type.h"
11 #include "ui/gfx/geometry/size.h"
12 
13 // Documentation on the format of the parameters for each clipboard target can
14 // be found in clipboard.h.
15 namespace ui {
16 
ScopedClipboardWriter(ClipboardBuffer buffer)17 ScopedClipboardWriter::ScopedClipboardWriter(ClipboardBuffer buffer)
18     : buffer_(buffer) {}
19 
~ScopedClipboardWriter()20 ScopedClipboardWriter::~ScopedClipboardWriter() {
21   static constexpr size_t kMaxRepresentations = 1 << 12;
22   DCHECK(objects_.empty() || platform_representations_.empty())
23       << "Portable and Platform representations should not be written on the "
24          "same write.";
25   DCHECK(platform_representations_.size() < kMaxRepresentations);
26   if (!objects_.empty()) {
27     Clipboard::GetForCurrentThread()->WritePortableRepresentations(buffer_,
28                                                                    objects_);
29   }
30   if (!platform_representations_.empty()) {
31     Clipboard::GetForCurrentThread()->WritePlatformRepresentations(
32         buffer_, std::move(platform_representations_));
33   }
34 }
35 
WriteText(const base::string16 & text)36 void ScopedClipboardWriter::WriteText(const base::string16& text) {
37   std::string utf8_text = base::UTF16ToUTF8(text);
38 
39   Clipboard::ObjectMapParams parameters;
40   parameters.push_back(
41       Clipboard::ObjectMapParam(utf8_text.begin(), utf8_text.end()));
42   objects_[Clipboard::PortableFormat::kText] = parameters;
43 }
44 
WriteHTML(const base::string16 & markup,const std::string & source_url)45 void ScopedClipboardWriter::WriteHTML(const base::string16& markup,
46                                       const std::string& source_url) {
47   std::string utf8_markup = base::UTF16ToUTF8(markup);
48 
49   Clipboard::ObjectMapParams parameters;
50   parameters.push_back(
51       Clipboard::ObjectMapParam(utf8_markup.begin(),
52                                 utf8_markup.end()));
53   if (!source_url.empty()) {
54     parameters.push_back(Clipboard::ObjectMapParam(source_url.begin(),
55                                                    source_url.end()));
56   }
57 
58   objects_[Clipboard::PortableFormat::kHtml] = parameters;
59 }
60 
WriteRTF(const std::string & rtf_data)61 void ScopedClipboardWriter::WriteRTF(const std::string& rtf_data) {
62   Clipboard::ObjectMapParams parameters;
63   parameters.push_back(Clipboard::ObjectMapParam(rtf_data.begin(),
64                                                  rtf_data.end()));
65   objects_[Clipboard::PortableFormat::kRtf] = parameters;
66 }
67 
WriteBookmark(const base::string16 & bookmark_title,const std::string & url)68 void ScopedClipboardWriter::WriteBookmark(const base::string16& bookmark_title,
69                                           const std::string& url) {
70   if (bookmark_title.empty() || url.empty())
71     return;
72 
73   std::string utf8_markup = base::UTF16ToUTF8(bookmark_title);
74 
75   Clipboard::ObjectMapParams parameters;
76   parameters.push_back(Clipboard::ObjectMapParam(utf8_markup.begin(),
77                                                  utf8_markup.end()));
78   parameters.push_back(Clipboard::ObjectMapParam(url.begin(), url.end()));
79   objects_[Clipboard::PortableFormat::kBookmark] = parameters;
80 }
81 
WriteHyperlink(const base::string16 & anchor_text,const std::string & url)82 void ScopedClipboardWriter::WriteHyperlink(const base::string16& anchor_text,
83                                            const std::string& url) {
84   if (anchor_text.empty() || url.empty())
85     return;
86 
87   // Construct the hyperlink.
88   std::string html = "<a href=\"";
89   html += net::EscapeForHTML(url);
90   html += "\">";
91   html += net::EscapeForHTML(base::UTF16ToUTF8(anchor_text));
92   html += "</a>";
93   WriteHTML(base::UTF8ToUTF16(html), std::string());
94 }
95 
WriteWebSmartPaste()96 void ScopedClipboardWriter::WriteWebSmartPaste() {
97   objects_[Clipboard::PortableFormat::kWebkit] = Clipboard::ObjectMapParams();
98 }
99 
WriteImage(const SkBitmap & bitmap)100 void ScopedClipboardWriter::WriteImage(const SkBitmap& bitmap) {
101   if (bitmap.drawsNothing())
102     return;
103   DCHECK(bitmap.getPixels());
104 
105   bitmap_ = bitmap;
106   // TODO(dcheng): This is slightly less horrible than what we used to do, but
107   // only very slightly less.
108   SkBitmap* bitmap_pointer = &bitmap_;
109   Clipboard::ObjectMapParam packed_pointer;
110   packed_pointer.resize(sizeof(bitmap_pointer));
111   *reinterpret_cast<SkBitmap**>(&*packed_pointer.begin()) = bitmap_pointer;
112   Clipboard::ObjectMapParams parameters;
113   parameters.push_back(packed_pointer);
114   objects_[Clipboard::PortableFormat::kBitmap] = parameters;
115 }
116 
WritePickledData(const base::Pickle & pickle,const ClipboardFormatType & format)117 void ScopedClipboardWriter::WritePickledData(
118     const base::Pickle& pickle,
119     const ClipboardFormatType& format) {
120   std::string format_string = format.Serialize();
121   Clipboard::ObjectMapParam format_parameter(format_string.begin(),
122                                              format_string.end());
123   Clipboard::ObjectMapParam data_parameter;
124 
125   data_parameter.resize(pickle.size());
126   memcpy(const_cast<char*>(&data_parameter.front()),
127          pickle.data(), pickle.size());
128 
129   Clipboard::ObjectMapParams parameters;
130   parameters.push_back(format_parameter);
131   parameters.push_back(data_parameter);
132   objects_[Clipboard::PortableFormat::kData] = parameters;
133 }
134 
WriteData(const base::string16 & format,mojo_base::BigBuffer data)135 void ScopedClipboardWriter::WriteData(const base::string16& format,
136                                       mojo_base::BigBuffer data) {
137   // Conservative limit to maximum format and data string size, to avoid
138   // potential attacks with long strings. Callers should implement similar
139   // checks.
140   constexpr size_t kMaxFormatSize = 1024;
141   constexpr size_t kMaxDataSize = 1 << 30;  // 1 GB
142   DCHECK_LT(format.size(), kMaxFormatSize);
143   DCHECK_LT(data.size(), kMaxDataSize);
144 
145   platform_representations_.push_back(
146       {base::UTF16ToUTF8(format), std::move(data)});
147 }
148 
Reset()149 void ScopedClipboardWriter::Reset() {
150   objects_.clear();
151   platform_representations_.clear();
152   bitmap_.reset();
153 }
154 
155 }  // namespace ui
156