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

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: Fixes for sky; ptal 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
« no previous file with comments | « ui/base/x/selection_utils.h ('k') | ui/base/x/x11_util.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 return std::string();
78
79 const unsigned char* front = memory->front();
80 return std::string(reinterpret_cast<const char*>(front), size);
81 }
82
83 string16 RefCountedMemoryToString16(
84 const scoped_refptr<base::RefCountedMemory>& memory) {
85 if (!memory) {
86 NOTREACHED();
87 return string16();
88 }
89
90 size_t size = memory->size();
91 if (!size)
92 return string16();
93
94 const unsigned char* front = memory->front();
95 return string16(reinterpret_cast<const base::char16*>(front), size / 2);
96 }
97
61 /////////////////////////////////////////////////////////////////////////////// 98 ///////////////////////////////////////////////////////////////////////////////
62 99
63 SelectionFormatMap::SelectionFormatMap() {} 100 SelectionFormatMap::SelectionFormatMap() {}
64 101
65 SelectionFormatMap::~SelectionFormatMap() { 102 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 103
72 for (std::set<char*>::iterator it = to_delete.begin(); it != to_delete.end(); 104 void SelectionFormatMap::Insert(
73 ++it) { 105 ::Atom atom,
74 delete [] *it; 106 const scoped_refptr<base::RefCountedMemory>& item) {
75 } 107 data_.insert(std::make_pair(atom, item));
76 } 108 }
77 109
78 void SelectionFormatMap::Insert(::Atom atom, char* data, size_t size) { 110 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 { 111 const std::vector< ::Atom>& requested_types) const {
99 for (std::vector< ::Atom>::const_iterator it = requested_types.begin(); 112 for (std::vector< ::Atom>::const_iterator it = requested_types.begin();
100 it != requested_types.end(); ++it) { 113 it != requested_types.end(); ++it) {
101 const_iterator data_it = data_.find(*it); 114 const_iterator data_it = data_.find(*it);
102 if (data_it != data_.end()) { 115 if (data_it != data_.end()) {
103 ui::SelectionData* data = new SelectionData; 116 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 } 117 }
108 } 118 }
109 119
110 return NULL; 120 return SelectionData();
111 } 121 }
112 122
113 std::vector< ::Atom> SelectionFormatMap::GetTypes() const { 123 std::vector< ::Atom> SelectionFormatMap::GetTypes() const {
114 std::vector< ::Atom> atoms; 124 std::vector< ::Atom> atoms;
115 for (const_iterator it = data_.begin(); it != data_.end(); ++it) 125 for (const_iterator it = data_.begin(); it != data_.end(); ++it)
116 atoms.push_back(it->first); 126 atoms.push_back(it->first);
117 127
118 return atoms; 128 return atoms;
119 } 129 }
120 130
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 /////////////////////////////////////////////////////////////////////////////// 131 ///////////////////////////////////////////////////////////////////////////////
134 132
135 SelectionData::SelectionData() 133 SelectionData::SelectionData()
136 : type_(None), 134 : type_(None),
137 data_(NULL),
138 size_(0),
139 owned_(false),
140 atom_cache_(ui::GetXDisplay(), kSelectionDataAtoms) { 135 atom_cache_(ui::GetXDisplay(), kSelectionDataAtoms) {
141 } 136 }
142 137
143 SelectionData::~SelectionData() { 138 SelectionData::SelectionData(
144 if (owned_) 139 ::Atom type,
145 XFree(data_); 140 const scoped_refptr<base::RefCountedMemory>& memory)
141 : type_(type),
142 memory_(memory),
143 atom_cache_(ui::GetXDisplay(), kSelectionDataAtoms) {
146 } 144 }
147 145
148 void SelectionData::Set(::Atom type, char* data, size_t size, bool owned) { 146 SelectionData::SelectionData(const SelectionData& rhs)
149 if (owned_) 147 : type_(rhs.type_),
150 XFree(data_); 148 memory_(rhs.memory_),
149 atom_cache_(ui::GetXDisplay(), kSelectionDataAtoms) {
150 }
151 151
152 type_ = type; 152 SelectionData::~SelectionData() {}
153 data_ = data; 153
154 size_ = size; 154 SelectionData& SelectionData::operator=(const SelectionData& rhs) {
155 owned_ = owned; 155 type_ = rhs.type_;
156 memory_ = rhs.memory_;
157 // TODO(erg): In some future where we have to support multiple X Displays,
158 // the following will also need to deal with the display.
159 return *this;
160 }
161
162 bool SelectionData::IsValid() const {
163 return type_ != None;
164 }
165
166 ::Atom SelectionData::GetType() const {
167 return type_;
168 }
169
170 const unsigned char* SelectionData::GetData() const {
171 return memory_ ? memory_->front() : NULL;
172 }
173
174 size_t SelectionData::GetSize() const {
175 return memory_ ? memory_->size() : 0;
156 } 176 }
157 177
158 std::string SelectionData::GetText() const { 178 std::string SelectionData::GetText() const {
159 if (type_ == atom_cache_.GetAtom(kUtf8String) || 179 if (type_ == atom_cache_.GetAtom(kUtf8String) ||
160 type_ == atom_cache_.GetAtom(kText)) { 180 type_ == atom_cache_.GetAtom(kText)) {
161 return std::string(data_, size_); 181 return RefCountedMemoryToString(memory_);
162 } else if (type_ == atom_cache_.GetAtom(kString)) { 182 } else if (type_ == atom_cache_.GetAtom(kString)) {
163 std::string result; 183 std::string result;
164 base::ConvertToUtf8AndNormalize(std::string(data_, size_), 184 base::ConvertToUtf8AndNormalize(RefCountedMemoryToString(memory_),
165 base::kCodepageLatin1, 185 base::kCodepageLatin1,
166 &result); 186 &result);
167 return result; 187 return result;
168 } else { 188 } else {
169 // BTW, I looked at COMPOUND_TEXT, and there's no way we're going to 189 // BTW, I looked at COMPOUND_TEXT, and there's no way we're going to
170 // support that. Yuck. 190 // support that. Yuck.
171 NOTREACHED(); 191 NOTREACHED();
172 return std::string(); 192 return std::string();
173 } 193 }
174 } 194 }
175 195
176 string16 SelectionData::GetHtml() const { 196 string16 SelectionData::GetHtml() const {
177 string16 markup; 197 string16 markup;
178 198
179 if (type_ == atom_cache_.GetAtom(Clipboard::kMimeTypeHTML)) { 199 if (type_ == atom_cache_.GetAtom(Clipboard::kMimeTypeHTML)) {
200 const unsigned char* data = GetData();
201 size_t size = GetSize();
202
180 // If the data starts with 0xFEFF, i.e., Byte Order Mark, assume it is 203 // If the data starts with 0xFEFF, i.e., Byte Order Mark, assume it is
181 // UTF-16, otherwise assume UTF-8. 204 // UTF-16, otherwise assume UTF-8.
182 if (size_ >= 2 && 205 if (size >= 2 &&
183 reinterpret_cast<const uint16_t*>(data_)[0] == 0xFEFF) { 206 reinterpret_cast<const uint16_t*>(data)[0] == 0xFEFF) {
184 markup.assign(reinterpret_cast<const uint16_t*>(data_) + 1, 207 markup.assign(reinterpret_cast<const uint16_t*>(data) + 1,
185 (size_ / 2) - 1); 208 (size / 2) - 1);
186 } else { 209 } else {
187 UTF8ToUTF16(reinterpret_cast<const char*>(data_), size_, &markup); 210 UTF8ToUTF16(reinterpret_cast<const char*>(data), size, &markup);
188 } 211 }
189 212
190 // If there is a terminating NULL, drop it. 213 // If there is a terminating NULL, drop it.
191 if (!markup.empty() && markup.at(markup.length() - 1) == '\0') 214 if (!markup.empty() && markup.at(markup.length() - 1) == '\0')
192 markup.resize(markup.length() - 1); 215 markup.resize(markup.length() - 1);
193 216
194 return markup; 217 return markup;
195 } else { 218 } else {
196 NOTREACHED(); 219 NOTREACHED();
197 return markup; 220 return markup;
198 } 221 }
199 } 222 }
200 223
201 void SelectionData::AssignTo(std::string* result) const { 224 void SelectionData::AssignTo(std::string* result) const {
202 result->assign(data_, size_); 225 *result = RefCountedMemoryToString(memory_);
203 } 226 }
204 227
205 void SelectionData::AssignTo(string16* result) const { 228 void SelectionData::AssignTo(string16* result) const {
206 result->assign(reinterpret_cast<base::char16*>(data_), size_ / 2); 229 *result = RefCountedMemoryToString16(memory_);
207 } 230 }
208 231
209 } // namespace ui 232 } // namespace ui
OLDNEW
« no previous file with comments | « ui/base/x/selection_utils.h ('k') | ui/base/x/x11_util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698