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