• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2013 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/x/selection_utils.h"
6 
7 #include <set>
8 
9 #include "base/i18n/icu_string_conversions.h"
10 #include "base/logging.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "ui/base/clipboard/clipboard.h"
13 #include "ui/base/x/x11_util.h"
14 #include "ui/gfx/x/x11_atom_cache.h"
15 
16 namespace ui {
17 
18 const char kMimeTypeMozillaURL[] = "text/x-moz-url";
19 const char kString[] = "STRING";
20 const char kText[] = "TEXT";
21 const char kUtf8String[] = "UTF8_STRING";
22 
23 const char* kSelectionDataAtoms[] = {
24   Clipboard::kMimeTypeHTML,
25   kString,
26   kText,
27   kUtf8String,
28   NULL
29 };
30 
GetTextAtomsFrom(const X11AtomCache * atom_cache)31 std::vector< ::Atom> GetTextAtomsFrom(const X11AtomCache* atom_cache) {
32   std::vector< ::Atom> atoms;
33   atoms.push_back(atom_cache->GetAtom(kUtf8String));
34   atoms.push_back(atom_cache->GetAtom(kString));
35   atoms.push_back(atom_cache->GetAtom(kText));
36   return atoms;
37 }
38 
GetURLAtomsFrom(const X11AtomCache * atom_cache)39 std::vector< ::Atom> GetURLAtomsFrom(const X11AtomCache* atom_cache) {
40   std::vector< ::Atom> atoms;
41   atoms.push_back(atom_cache->GetAtom(Clipboard::kMimeTypeURIList));
42   atoms.push_back(atom_cache->GetAtom(kMimeTypeMozillaURL));
43   return atoms;
44 }
45 
GetAtomIntersection(const std::vector<::Atom> & desired,const std::vector<::Atom> & offered,std::vector<::Atom> * output)46 void GetAtomIntersection(const std::vector< ::Atom>& desired,
47                          const std::vector< ::Atom>& offered,
48                          std::vector< ::Atom>* output) {
49   for (std::vector< ::Atom>::const_iterator it = desired.begin();
50        it != desired.end(); ++it) {
51     std::vector< ::Atom>::const_iterator jt =
52       std::find(offered.begin(), offered.end(), *it);
53     if (jt != offered.end())
54       output->push_back(*it);
55   }
56 }
57 
AddString16ToVector(const string16 & str,std::vector<unsigned char> * bytes)58 void AddString16ToVector(const string16& str,
59                          std::vector<unsigned char>* bytes) {
60   const unsigned char* front =
61       reinterpret_cast<const unsigned char*>(str.data());
62   bytes->insert(bytes->end(), front, front + (str.size() * 2));
63 }
64 
RefCountedMemoryToString(const scoped_refptr<base::RefCountedMemory> & memory)65 std::string RefCountedMemoryToString(
66     const scoped_refptr<base::RefCountedMemory>& memory) {
67   if (!memory.get()) {
68     NOTREACHED();
69     return std::string();
70   }
71 
72   size_t size = memory->size();
73   if (!size)
74     return std::string();
75 
76   const unsigned char* front = memory->front();
77   return std::string(reinterpret_cast<const char*>(front), size);
78 }
79 
RefCountedMemoryToString16(const scoped_refptr<base::RefCountedMemory> & memory)80 string16 RefCountedMemoryToString16(
81     const scoped_refptr<base::RefCountedMemory>& memory) {
82   if (!memory.get()) {
83     NOTREACHED();
84     return string16();
85   }
86 
87   size_t size = memory->size();
88   if (!size)
89     return string16();
90 
91   const unsigned char* front = memory->front();
92   return string16(reinterpret_cast<const base::char16*>(front), size / 2);
93 }
94 
95 ///////////////////////////////////////////////////////////////////////////////
96 
SelectionFormatMap()97 SelectionFormatMap::SelectionFormatMap() {}
98 
~SelectionFormatMap()99 SelectionFormatMap::~SelectionFormatMap() {}
100 
Insert(::Atom atom,const scoped_refptr<base::RefCountedMemory> & item)101 void SelectionFormatMap::Insert(
102     ::Atom atom,
103     const scoped_refptr<base::RefCountedMemory>& item) {
104   data_.erase(atom);
105   data_.insert(std::make_pair(atom, item));
106 }
107 
GetFirstOf(const std::vector<::Atom> & requested_types) const108 ui::SelectionData SelectionFormatMap::GetFirstOf(
109     const std::vector< ::Atom>& requested_types) const {
110   for (std::vector< ::Atom>::const_iterator it = requested_types.begin();
111        it != requested_types.end(); ++it) {
112     const_iterator data_it = data_.find(*it);
113     if (data_it != data_.end()) {
114       return SelectionData(data_it->first, data_it->second);
115     }
116   }
117 
118   return SelectionData();
119 }
120 
GetTypes() const121 std::vector< ::Atom> SelectionFormatMap::GetTypes() const {
122   std::vector< ::Atom> atoms;
123   for (const_iterator it = data_.begin(); it != data_.end(); ++it)
124     atoms.push_back(it->first);
125 
126   return atoms;
127 }
128 
129 ///////////////////////////////////////////////////////////////////////////////
130 
SelectionData()131 SelectionData::SelectionData()
132     : type_(None),
133       atom_cache_(gfx::GetXDisplay(), kSelectionDataAtoms) {
134 }
135 
SelectionData(::Atom type,const scoped_refptr<base::RefCountedMemory> & memory)136 SelectionData::SelectionData(
137     ::Atom type,
138     const scoped_refptr<base::RefCountedMemory>& memory)
139     : type_(type),
140       memory_(memory),
141       atom_cache_(gfx::GetXDisplay(), kSelectionDataAtoms) {
142 }
143 
SelectionData(const SelectionData & rhs)144 SelectionData::SelectionData(const SelectionData& rhs)
145     : type_(rhs.type_),
146       memory_(rhs.memory_),
147       atom_cache_(gfx::GetXDisplay(), kSelectionDataAtoms) {
148 }
149 
~SelectionData()150 SelectionData::~SelectionData() {}
151 
operator =(const SelectionData & rhs)152 SelectionData& SelectionData::operator=(const SelectionData& rhs) {
153   type_ = rhs.type_;
154   memory_ = rhs.memory_;
155   // TODO(erg): In some future where we have to support multiple X Displays,
156   // the following will also need to deal with the display.
157   return *this;
158 }
159 
IsValid() const160 bool SelectionData::IsValid() const {
161   return type_ != None;
162 }
163 
GetType() const164 ::Atom SelectionData::GetType() const {
165   return type_;
166 }
167 
GetData() const168 const unsigned char* SelectionData::GetData() const {
169   return memory_.get() ? memory_->front() : NULL;
170 }
171 
GetSize() const172 size_t SelectionData::GetSize() const {
173   return memory_.get() ? memory_->size() : 0;
174 }
175 
GetText() const176 std::string SelectionData::GetText() const {
177   if (type_ == atom_cache_.GetAtom(kUtf8String) ||
178       type_ == atom_cache_.GetAtom(kText)) {
179     return RefCountedMemoryToString(memory_);
180   } else if (type_ == atom_cache_.GetAtom(kString)) {
181     std::string result;
182     base::ConvertToUtf8AndNormalize(RefCountedMemoryToString(memory_),
183                                     base::kCodepageLatin1,
184                                     &result);
185     return result;
186   } else {
187     // BTW, I looked at COMPOUND_TEXT, and there's no way we're going to
188     // support that. Yuck.
189     NOTREACHED();
190     return std::string();
191   }
192 }
193 
GetHtml() const194 string16 SelectionData::GetHtml() const {
195   string16 markup;
196 
197   if (type_ == atom_cache_.GetAtom(Clipboard::kMimeTypeHTML)) {
198     const unsigned char* data = GetData();
199     size_t size = GetSize();
200 
201     // If the data starts with 0xFEFF, i.e., Byte Order Mark, assume it is
202     // UTF-16, otherwise assume UTF-8.
203     if (size >= 2 &&
204         reinterpret_cast<const uint16_t*>(data)[0] == 0xFEFF) {
205       markup.assign(reinterpret_cast<const uint16_t*>(data) + 1,
206                     (size / 2) - 1);
207     } else {
208       UTF8ToUTF16(reinterpret_cast<const char*>(data), size, &markup);
209     }
210 
211     // If there is a terminating NULL, drop it.
212     if (!markup.empty() && markup.at(markup.length() - 1) == '\0')
213       markup.resize(markup.length() - 1);
214 
215     return markup;
216   } else {
217     NOTREACHED();
218     return markup;
219   }
220 }
221 
AssignTo(std::string * result) const222 void SelectionData::AssignTo(std::string* result) const {
223   *result = RefCountedMemoryToString(memory_);
224 }
225 
AssignTo(string16 * result) const226 void SelectionData::AssignTo(string16* result) const {
227   *result = RefCountedMemoryToString16(memory_);
228 }
229 
230 }  // namespace ui
231