| Index: ui/base/x/selection_utils.cc
 | 
| diff --git a/ui/base/x/selection_utils.cc b/ui/base/x/selection_utils.cc
 | 
| index 5dd6f681ce129ab01388a4068fcd5154410dffc5..560f494a0c6c1b94c598cb52f1df03d8a74abf68 100644
 | 
| --- a/ui/base/x/selection_utils.cc
 | 
| +++ b/ui/base/x/selection_utils.cc
 | 
| @@ -58,56 +58,66 @@ void GetAtomIntersection(const std::vector< ::Atom>& one,
 | 
|    }
 | 
|  }
 | 
|  
 | 
| -///////////////////////////////////////////////////////////////////////////////
 | 
| +void AddString16ToVector(const string16& str,
 | 
| +                         std::vector<unsigned char>* bytes) {
 | 
| +  const unsigned char* front =
 | 
| +      reinterpret_cast<const unsigned char*>(str.data());
 | 
| +  bytes->insert(bytes->end(), front, front + (str.size() * 2));
 | 
| +}
 | 
|  
 | 
| -SelectionFormatMap::SelectionFormatMap() {}
 | 
| +std::string RefCountedMemoryToString(
 | 
| +    const scoped_refptr<base::RefCountedMemory>& memory) {
 | 
| +  if (!memory) {
 | 
| +    NOTREACHED();
 | 
| +    return std::string();
 | 
| +  }
 | 
|  
 | 
| -SelectionFormatMap::~SelectionFormatMap() {
 | 
| -  // WriteText() inserts the same pointer multiple times for different
 | 
| -  // representations; we need to dedupe it.
 | 
| -  std::set<char*> to_delete;
 | 
| -  for (InternalMap::iterator it = data_.begin(); it != data_.end(); ++it)
 | 
| -    to_delete.insert(it->second.first);
 | 
| +  size_t size = memory->size();
 | 
| +  if (!size)
 | 
| +    return std::string();
 | 
|  
 | 
| -  for (std::set<char*>::iterator it = to_delete.begin(); it != to_delete.end();
 | 
| -       ++it) {
 | 
| -    delete [] *it;
 | 
| +  const unsigned char* front = memory->front();
 | 
| +  return std::string(reinterpret_cast<const char*>(front), size);
 | 
| +}
 | 
| +
 | 
| +string16 RefCountedMemoryToString16(
 | 
| +    const scoped_refptr<base::RefCountedMemory>& memory) {
 | 
| +  if (!memory) {
 | 
| +    NOTREACHED();
 | 
| +    return string16();
 | 
|    }
 | 
| +
 | 
| +  size_t size = memory->size();
 | 
| +  if (!size)
 | 
| +    return string16();
 | 
| +
 | 
| +  const unsigned char* front = memory->front();
 | 
| +  return string16(reinterpret_cast<const base::char16*>(front), size / 2);
 | 
|  }
 | 
|  
 | 
| -void SelectionFormatMap::Insert(::Atom atom, char* data, size_t size) {
 | 
| -  // Views code often inserts the same content multiple times, so we have to
 | 
| -  // free old data. Only call delete when it's the last pointer we have to that
 | 
| -  // data.
 | 
| -  InternalMap::iterator exists_it = data_.find(atom);
 | 
| -  if (exists_it != data_.end()) {
 | 
| -    int count = 0;
 | 
| -    for (InternalMap::iterator it = data_.begin(); it != data_.end(); ++it) {
 | 
| -      if (it->second.first == exists_it->second.first)
 | 
| -        count++;
 | 
| -    }
 | 
| +///////////////////////////////////////////////////////////////////////////////
 | 
|  
 | 
| -    if (count == 1)
 | 
| -      delete [] exists_it->second.first;
 | 
| -  }
 | 
| +SelectionFormatMap::SelectionFormatMap() {}
 | 
| +
 | 
| +SelectionFormatMap::~SelectionFormatMap() {}
 | 
|  
 | 
| -  data_.insert(std::make_pair(atom, std::make_pair(data, size)));
 | 
| +void SelectionFormatMap::Insert(
 | 
| +    ::Atom atom,
 | 
| +    const scoped_refptr<base::RefCountedMemory>& item) {
 | 
| +  data_.insert(std::make_pair(atom, item));
 | 
|  }
 | 
|  
 | 
| -ui::SelectionData* SelectionFormatMap::GetFirstOf(
 | 
| +ui::SelectionData SelectionFormatMap::GetFirstOf(
 | 
|      const std::vector< ::Atom>& requested_types) const {
 | 
|    for (std::vector< ::Atom>::const_iterator it = requested_types.begin();
 | 
|         it != requested_types.end(); ++it) {
 | 
|      const_iterator data_it = data_.find(*it);
 | 
|      if (data_it != data_.end()) {
 | 
| -      ui::SelectionData* data = new SelectionData;
 | 
| -      data->Set(data_it->first, data_it->second.first, data_it->second.second,
 | 
| -                false);
 | 
| -      return data;
 | 
| +      return SelectionData(data_it->first, data_it->second);
 | 
|      }
 | 
|    }
 | 
|  
 | 
| -  return NULL;
 | 
| +  return SelectionData();
 | 
|  }
 | 
|  
 | 
|  std::vector< ::Atom> SelectionFormatMap::GetTypes() const {
 | 
| @@ -118,50 +128,60 @@ std::vector< ::Atom> SelectionFormatMap::GetTypes() const {
 | 
|    return atoms;
 | 
|  }
 | 
|  
 | 
| -scoped_ptr<SelectionFormatMap> SelectionFormatMap::Clone() const {
 | 
| -  scoped_ptr<SelectionFormatMap> ret(new SelectionFormatMap);
 | 
| -
 | 
| -  for (const_iterator it = data_.begin(); it != data_.end(); ++it) {
 | 
| -    char* data_copy = new char[it->second.second];
 | 
| -    memcpy(data_copy, it->second.first, it->second.second);
 | 
| -    ret->Insert(it->first, data_copy, it->second.second);
 | 
| -  }
 | 
| -
 | 
| -  return ret.Pass();
 | 
| -}
 | 
| -
 | 
|  ///////////////////////////////////////////////////////////////////////////////
 | 
|  
 | 
|  SelectionData::SelectionData()
 | 
|      : type_(None),
 | 
| -      data_(NULL),
 | 
| -      size_(0),
 | 
| -      owned_(false),
 | 
|        atom_cache_(ui::GetXDisplay(), kSelectionDataAtoms) {
 | 
|  }
 | 
|  
 | 
| -SelectionData::~SelectionData() {
 | 
| -  if (owned_)
 | 
| -    XFree(data_);
 | 
| +SelectionData::SelectionData(
 | 
| +    ::Atom type,
 | 
| +    const scoped_refptr<base::RefCountedMemory>& memory)
 | 
| +    : type_(type),
 | 
| +      memory_(memory),
 | 
| +      atom_cache_(ui::GetXDisplay(), kSelectionDataAtoms) {
 | 
| +}
 | 
| +
 | 
| +SelectionData::SelectionData(const SelectionData& rhs)
 | 
| +    : type_(rhs.type_),
 | 
| +      memory_(rhs.memory_),
 | 
| +      atom_cache_(ui::GetXDisplay(), kSelectionDataAtoms) {
 | 
| +}
 | 
| +
 | 
| +SelectionData::~SelectionData() {}
 | 
| +
 | 
| +SelectionData& SelectionData::operator=(const SelectionData& rhs) {
 | 
| +  type_ = rhs.type_;
 | 
| +  memory_ = rhs.memory_;
 | 
| +  // TODO(erg): In some future where we have to support multiple X Displays,
 | 
| +  // the following will also need to deal with the display.
 | 
| +  return *this;
 | 
|  }
 | 
|  
 | 
| -void SelectionData::Set(::Atom type, char* data, size_t size, bool owned) {
 | 
| -  if (owned_)
 | 
| -    XFree(data_);
 | 
| +bool SelectionData::IsValid() const {
 | 
| +  return type_ != None;
 | 
| +}
 | 
|  
 | 
| -  type_ = type;
 | 
| -  data_ = data;
 | 
| -  size_ = size;
 | 
| -  owned_ = owned;
 | 
| +::Atom SelectionData::GetType() const {
 | 
| +  return type_;
 | 
| +}
 | 
| +
 | 
| +const unsigned char* SelectionData::GetData() const {
 | 
| +  return memory_ ? memory_->front() : NULL;
 | 
| +}
 | 
| +
 | 
| +size_t SelectionData::GetSize() const {
 | 
| +  return memory_ ? memory_->size() : 0;
 | 
|  }
 | 
|  
 | 
|  std::string SelectionData::GetText() const {
 | 
|    if (type_ == atom_cache_.GetAtom(kUtf8String) ||
 | 
|        type_ == atom_cache_.GetAtom(kText)) {
 | 
| -    return std::string(data_, size_);
 | 
| +    return RefCountedMemoryToString(memory_);
 | 
|    } else if (type_ == atom_cache_.GetAtom(kString)) {
 | 
|      std::string result;
 | 
| -    base::ConvertToUtf8AndNormalize(std::string(data_, size_),
 | 
| +    base::ConvertToUtf8AndNormalize(RefCountedMemoryToString(memory_),
 | 
|                                      base::kCodepageLatin1,
 | 
|                                      &result);
 | 
|      return result;
 | 
| @@ -177,14 +197,17 @@ string16 SelectionData::GetHtml() const {
 | 
|    string16 markup;
 | 
|  
 | 
|    if (type_ == atom_cache_.GetAtom(Clipboard::kMimeTypeHTML)) {
 | 
| +    const unsigned char* data = GetData();
 | 
| +    size_t size = GetSize();
 | 
| +
 | 
|      // If the data starts with 0xFEFF, i.e., Byte Order Mark, assume it is
 | 
|      // UTF-16, otherwise assume UTF-8.
 | 
| -    if (size_ >= 2 &&
 | 
| -        reinterpret_cast<const uint16_t*>(data_)[0] == 0xFEFF) {
 | 
| -      markup.assign(reinterpret_cast<const uint16_t*>(data_) + 1,
 | 
| -                    (size_ / 2) - 1);
 | 
| +    if (size >= 2 &&
 | 
| +        reinterpret_cast<const uint16_t*>(data)[0] == 0xFEFF) {
 | 
| +      markup.assign(reinterpret_cast<const uint16_t*>(data) + 1,
 | 
| +                    (size / 2) - 1);
 | 
|      } else {
 | 
| -      UTF8ToUTF16(reinterpret_cast<const char*>(data_), size_, &markup);
 | 
| +      UTF8ToUTF16(reinterpret_cast<const char*>(data), size, &markup);
 | 
|      }
 | 
|  
 | 
|      // If there is a terminating NULL, drop it.
 | 
| @@ -199,11 +222,11 @@ string16 SelectionData::GetHtml() const {
 | 
|  }
 | 
|  
 | 
|  void SelectionData::AssignTo(std::string* result) const {
 | 
| -  result->assign(data_, size_);
 | 
| +  *result = RefCountedMemoryToString(memory_);
 | 
|  }
 | 
|  
 | 
|  void SelectionData::AssignTo(string16* result) const {
 | 
| -  result->assign(reinterpret_cast<base::char16*>(data_), size_ / 2);
 | 
| +  *result = RefCountedMemoryToString16(memory_);
 | 
|  }
 | 
|  
 | 
|  }  // namespace ui
 | 
| 
 |