Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(29)

Side by Side Diff: ui/base/x/selection_utils.cc

Issue 17029020: linux_aura: Redo how memory is handled in clipboard/drag code. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/base/x/selection_utils.h" 5 #include "ui/base/x/selection_utils.h"
6 6
7 #include <set> 7 #include <set>
8 8
9 #include "base/i18n/icu_string_conversions.h" 9 #include "base/i18n/icu_string_conversions.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
51 for (std::vector< ::Atom>::const_iterator jt = two.begin(); jt != two.end(); 51 for (std::vector< ::Atom>::const_iterator jt = two.begin(); jt != two.end();
52 ++jt) { 52 ++jt) {
53 if (*it == *jt) { 53 if (*it == *jt) {
54 output->push_back(*it); 54 output->push_back(*it);
55 break; 55 break;
56 } 56 }
57 } 57 }
58 } 58 }
59 } 59 }
60 60
61 void AddString16ToVector(const string16& str,
62 std::vector<unsigned char>* bytes) {
63 const unsigned char* front =
64 reinterpret_cast<const unsigned char*>(str.data());
65 bytes->insert(bytes->end(), front, front + (str.size() * 2));
66 }
67
68 std::string RefCountedMemoryToString(
69 const scoped_refptr<base::RefCountedMemory>& memory) {
70 if (!memory) {
71 NOTREACHED();
72 return std::string();
73 }
74
75 size_t size = memory->size();
76 if (!size) {
77 NOTREACHED();
sky 2013/06/24 20:36:18 Is an empty string not legal?
Elliot Glaysher 2013/06/24 20:54:35 I want to say that it's impossible, but I'm not ac
78 return std::string();
79 }
80
81 const unsigned char* front = memory->front();
82 return std::string(reinterpret_cast<const char*>(front), size);
83 }
84
85 string16 RefCountedMemoryToString16(
86 const scoped_refptr<base::RefCountedMemory>& memory) {
87 if (!memory) {
88 NOTREACHED();
89 return string16();
90 }
91
92 size_t size = memory->size();
93 if (!size) {
94 NOTREACHED();
95 return string16();
96 }
97
98 const unsigned char* front = memory->front();
99 return string16(reinterpret_cast<const base::char16*>(front), size / 2);
100 }
101
61 /////////////////////////////////////////////////////////////////////////////// 102 ///////////////////////////////////////////////////////////////////////////////
62 103
63 SelectionFormatMap::SelectionFormatMap() {} 104 SelectionFormatMap::SelectionFormatMap() {}
64 105
65 SelectionFormatMap::~SelectionFormatMap() { 106 SelectionFormatMap::~SelectionFormatMap() {}
66 // WriteText() inserts the same pointer multiple times for different
67 // representations; we need to dedupe it.
68 std::set<char*> to_delete;
69 for (InternalMap::iterator it = data_.begin(); it != data_.end(); ++it)
70 to_delete.insert(it->second.first);
71 107
72 for (std::set<char*>::iterator it = to_delete.begin(); it != to_delete.end(); 108 void SelectionFormatMap::Insert(
73 ++it) { 109 ::Atom atom,
74 delete [] *it; 110 const scoped_refptr<base::RefCountedMemory>& item) {
75 } 111 data_.insert(std::make_pair(atom, item));
76 } 112 }
77 113
78 void SelectionFormatMap::Insert(::Atom atom, char* data, size_t size) { 114 ui::SelectionData SelectionFormatMap::GetFirstOf(
79 // Views code often inserts the same content multiple times, so we have to
80 // free old data. Only call delete when it's the last pointer we have to that
81 // data.
82 InternalMap::iterator exists_it = data_.find(atom);
83 if (exists_it != data_.end()) {
84 int count = 0;
85 for (InternalMap::iterator it = data_.begin(); it != data_.end(); ++it) {
86 if (it->second.first == exists_it->second.first)
87 count++;
88 }
89
90 if (count == 1)
91 delete [] exists_it->second.first;
92 }
93
94 data_.insert(std::make_pair(atom, std::make_pair(data, size)));
95 }
96
97 ui::SelectionData* SelectionFormatMap::GetFirstOf(
98 const std::vector< ::Atom>& requested_types) const { 115 const std::vector< ::Atom>& requested_types) const {
99 for (std::vector< ::Atom>::const_iterator it = requested_types.begin(); 116 for (std::vector< ::Atom>::const_iterator it = requested_types.begin();
100 it != requested_types.end(); ++it) { 117 it != requested_types.end(); ++it) {
101 const_iterator data_it = data_.find(*it); 118 const_iterator data_it = data_.find(*it);
102 if (data_it != data_.end()) { 119 if (data_it != data_.end()) {
103 ui::SelectionData* data = new SelectionData; 120 return SelectionData(data_it->first, data_it->second);
104 data->Set(data_it->first, data_it->second.first, data_it->second.second,
105 false);
106 return data;
107 } 121 }
108 } 122 }
109 123
110 return NULL; 124 return SelectionData();
111 } 125 }
112 126
113 std::vector< ::Atom> SelectionFormatMap::GetTypes() const { 127 std::vector< ::Atom> SelectionFormatMap::GetTypes() const {
114 std::vector< ::Atom> atoms; 128 std::vector< ::Atom> atoms;
115 for (const_iterator it = data_.begin(); it != data_.end(); ++it) 129 for (const_iterator it = data_.begin(); it != data_.end(); ++it)
116 atoms.push_back(it->first); 130 atoms.push_back(it->first);
117 131
118 return atoms; 132 return atoms;
119 } 133 }
120 134
121 scoped_ptr<SelectionFormatMap> SelectionFormatMap::Clone() const {
122 scoped_ptr<SelectionFormatMap> ret(new SelectionFormatMap);
123
124 for (const_iterator it = data_.begin(); it != data_.end(); ++it) {
125 char* data_copy = new char[it->second.second];
126 memcpy(data_copy, it->second.first, it->second.second);
127 ret->Insert(it->first, data_copy, it->second.second);
128 }
129
130 return ret.Pass();
131 }
132
133 /////////////////////////////////////////////////////////////////////////////// 135 ///////////////////////////////////////////////////////////////////////////////
134 136
135 SelectionData::SelectionData() 137 SelectionData::SelectionData()
136 : type_(None), 138 : type_(None),
137 data_(NULL),
138 size_(0),
139 owned_(false),
140 atom_cache_(ui::GetXDisplay(), kSelectionDataAtoms) { 139 atom_cache_(ui::GetXDisplay(), kSelectionDataAtoms) {
141 } 140 }
142 141
143 SelectionData::~SelectionData() { 142 SelectionData::SelectionData(
144 if (owned_) 143 ::Atom type,
145 XFree(data_); 144 const scoped_refptr<base::RefCountedMemory>& memory)
145 : type_(type),
146 memory_(memory),
147 atom_cache_(ui::GetXDisplay(), kSelectionDataAtoms) {
146 } 148 }
147 149
148 void SelectionData::Set(::Atom type, char* data, size_t size, bool owned) { 150 SelectionData::SelectionData(const SelectionData& rhs)
149 if (owned_) 151 : type_(rhs.type_),
150 XFree(data_); 152 memory_(rhs.memory_),
153 atom_cache_(ui::GetXDisplay(), kSelectionDataAtoms) {
154 }
151 155
152 type_ = type; 156 SelectionData::~SelectionData() {}
153 data_ = data; 157
154 size_ = size; 158 SelectionData& SelectionData::operator=(const SelectionData& rhs) {
155 owned_ = owned; 159 type_ = rhs.type_;
160 memory_ = rhs.memory_;
161 // TODO(erg): In some future where we have to support multiple X Displays,
162 // the following will also need to deal with the display.
163 return *this;
164 }
165
166 bool SelectionData::IsValid() const {
167 return type_ != None;
168 }
169
170 ::Atom SelectionData::GetType() const {
171 return type_;
172 }
173
174 const unsigned char* SelectionData::GetData() const {
175 return memory_ ? memory_->front() : NULL;
176 }
177
178 size_t SelectionData::GetSize() const {
179 return memory_ ? memory_->size() : 0;
156 } 180 }
157 181
158 std::string SelectionData::GetText() const { 182 std::string SelectionData::GetText() const {
159 if (type_ == atom_cache_.GetAtom(kUtf8String) || 183 if (type_ == atom_cache_.GetAtom(kUtf8String) ||
160 type_ == atom_cache_.GetAtom(kText)) { 184 type_ == atom_cache_.GetAtom(kText)) {
161 return std::string(data_, size_); 185 return RefCountedMemoryToString(memory_);
162 } else if (type_ == atom_cache_.GetAtom(kString)) { 186 } else if (type_ == atom_cache_.GetAtom(kString)) {
163 std::string result; 187 std::string result;
164 base::ConvertToUtf8AndNormalize(std::string(data_, size_), 188 base::ConvertToUtf8AndNormalize(RefCountedMemoryToString(memory_),
165 base::kCodepageLatin1, 189 base::kCodepageLatin1,
166 &result); 190 &result);
167 return result; 191 return result;
168 } else { 192 } else {
169 // BTW, I looked at COMPOUND_TEXT, and there's no way we're going to 193 // BTW, I looked at COMPOUND_TEXT, and there's no way we're going to
170 // support that. Yuck. 194 // support that. Yuck.
171 NOTREACHED(); 195 NOTREACHED();
172 return std::string(); 196 return std::string();
173 } 197 }
174 } 198 }
175 199
176 string16 SelectionData::GetHtml() const { 200 string16 SelectionData::GetHtml() const {
177 string16 markup; 201 string16 markup;
178 202
179 if (type_ == atom_cache_.GetAtom(Clipboard::kMimeTypeHTML)) { 203 if (type_ == atom_cache_.GetAtom(Clipboard::kMimeTypeHTML)) {
204 const unsigned char* data = GetData();
205 size_t size = GetSize();
206
180 // If the data starts with 0xFEFF, i.e., Byte Order Mark, assume it is 207 // If the data starts with 0xFEFF, i.e., Byte Order Mark, assume it is
181 // UTF-16, otherwise assume UTF-8. 208 // UTF-16, otherwise assume UTF-8.
182 if (size_ >= 2 && 209 if (size >= 2 &&
183 reinterpret_cast<const uint16_t*>(data_)[0] == 0xFEFF) { 210 reinterpret_cast<const uint16_t*>(data)[0] == 0xFEFF) {
184 markup.assign(reinterpret_cast<const uint16_t*>(data_) + 1, 211 markup.assign(reinterpret_cast<const uint16_t*>(data) + 1,
185 (size_ / 2) - 1); 212 (size / 2) - 1);
186 } else { 213 } else {
187 UTF8ToUTF16(reinterpret_cast<const char*>(data_), size_, &markup); 214 UTF8ToUTF16(reinterpret_cast<const char*>(data), size, &markup);
188 } 215 }
189 216
190 // If there is a terminating NULL, drop it. 217 // If there is a terminating NULL, drop it.
191 if (!markup.empty() && markup.at(markup.length() - 1) == '\0') 218 if (!markup.empty() && markup.at(markup.length() - 1) == '\0')
192 markup.resize(markup.length() - 1); 219 markup.resize(markup.length() - 1);
193 220
194 return markup; 221 return markup;
195 } else { 222 } else {
196 NOTREACHED(); 223 NOTREACHED();
197 return markup; 224 return markup;
198 } 225 }
199 } 226 }
200 227
201 void SelectionData::AssignTo(std::string* result) const { 228 void SelectionData::AssignTo(std::string* result) const {
202 result->assign(data_, size_); 229 *result = RefCountedMemoryToString(memory_);
203 } 230 }
204 231
205 void SelectionData::AssignTo(string16* result) const { 232 void SelectionData::AssignTo(string16* result) const {
206 result->assign(reinterpret_cast<base::char16*>(data_), size_ / 2); 233 *result = RefCountedMemoryToString16(memory_);
207 } 234 }
208 235
209 } // namespace ui 236 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698