summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ui/base/clipboard/clipboard_aurax11.cc174
-rw-r--r--ui/base/dragdrop/os_exchange_data_provider_aurax11.cc62
-rw-r--r--ui/base/dragdrop/os_exchange_data_provider_aurax11.h7
-rw-r--r--ui/base/x/selection_owner.cc73
-rw-r--r--ui/base/x/selection_owner.h9
-rw-r--r--ui/base/x/selection_requestor.cc12
-rw-r--r--ui/base/x/selection_requestor.h15
-rw-r--r--ui/base/x/selection_utils.cc155
-rw-r--r--ui/base/x/selection_utils.h45
-rw-r--r--ui/base/x/x11_util.cc58
-rw-r--r--ui/base/x/x11_util.h37
-rw-r--r--ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc32
-rw-r--r--ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h4
13 files changed, 360 insertions, 323 deletions
diff --git a/ui/base/clipboard/clipboard_aurax11.cc b/ui/base/clipboard/clipboard_aurax11.cc
index 8809d26..287941d 100644
--- a/ui/base/clipboard/clipboard_aurax11.cc
+++ b/ui/base/clipboard/clipboard_aurax11.cc
@@ -239,7 +239,7 @@ class Clipboard::AuraX11Details : public base::MessagePumpDispatcher {
SelectionRequestor* GetSelectionRequestorForBuffer(Buffer buffer);
// Finds the SelectionFormatMap for the incoming selection atom.
- SelectionFormatMap* LookupStorageForAtom(::Atom atom);
+ const SelectionFormatMap& LookupStorageForAtom(::Atom atom);
// As we need to collect all the data types before we tell X11 that we own a
// particular selection, we create a temporary clipboard mapping that
@@ -248,7 +248,8 @@ class Clipboard::AuraX11Details : public base::MessagePumpDispatcher {
void CreateNewClipboardData();
// Inserts a mapping into clipboard_data_.
- void InsertMapping(const std::string& key, char* data, size_t data_len);
+ void InsertMapping(const std::string& key,
+ const scoped_refptr<base::RefCountedMemory>& memory);
// Moves the temporary |clipboard_data_| to the long term data storage for
// |buffer|.
@@ -262,9 +263,8 @@ class Clipboard::AuraX11Details : public base::MessagePumpDispatcher {
// selection holder is some other window, we spin up a nested message loop
// and do the asynchronous dance with whatever application is holding the
// selection.
- scoped_ptr<SelectionData> RequestAndWaitForTypes(
- Buffer buffer,
- const std::vector< ::Atom>& types);
+ ui::SelectionData RequestAndWaitForTypes(Buffer buffer,
+ const std::vector< ::Atom>& types);
// Retrieves the list of possible data types the current clipboard owner has.
//
@@ -299,7 +299,7 @@ class Clipboard::AuraX11Details : public base::MessagePumpDispatcher {
SelectionRequestor primary_requestor_;
// Temporary target map that we write to during DispatchObects.
- scoped_ptr<SelectionFormatMap> clipboard_data_;
+ SelectionFormatMap clipboard_data_;
// Objects which offer selection data to other windows.
SelectionOwner clipboard_owner_;
@@ -345,18 +345,17 @@ Clipboard::AuraX11Details::~AuraX11Details() {
Buffer buffer) const {
if (buffer == BUFFER_STANDARD)
return atom_cache_.GetAtom(kClipboard);
- else
- return XA_PRIMARY;
+
+ return XA_PRIMARY;
}
-SelectionFormatMap* Clipboard::AuraX11Details::LookupStorageForAtom(
+const SelectionFormatMap& Clipboard::AuraX11Details::LookupStorageForAtom(
::Atom atom) {
if (atom == XA_PRIMARY)
return primary_owner_.selection_format_map();
- else if (atom == atom_cache_.GetAtom(kClipboard))
- return clipboard_owner_.selection_format_map();
- else
- return NULL;
+
+ DCHECK_EQ(atom_cache_.GetAtom(kClipboard), atom);
+ return clipboard_owner_.selection_format_map();
}
ui::SelectionRequestor*
@@ -368,42 +367,37 @@ Clipboard::AuraX11Details::GetSelectionRequestorForBuffer(Buffer buffer) {
}
void Clipboard::AuraX11Details::CreateNewClipboardData() {
- clipboard_data_.reset(new SelectionFormatMap);
+ clipboard_data_ = SelectionFormatMap();
}
-void Clipboard::AuraX11Details::InsertMapping(const std::string& key,
- char* data,
- size_t data_len) {
+void Clipboard::AuraX11Details::InsertMapping(
+ const std::string& key,
+ const scoped_refptr<base::RefCountedMemory>& memory) {
::Atom atom_key = atom_cache_.GetAtom(key.c_str());
- clipboard_data_->Insert(atom_key, data, data_len);
+ clipboard_data_.Insert(atom_key, memory);
}
void Clipboard::AuraX11Details::TakeOwnershipOfSelection(Buffer buffer) {
if (buffer == BUFFER_STANDARD)
- return clipboard_owner_.TakeOwnershipOfSelection(clipboard_data_.Pass());
+ return clipboard_owner_.TakeOwnershipOfSelection(clipboard_data_);
else
- return primary_owner_.TakeOwnershipOfSelection(clipboard_data_.Pass());
+ return primary_owner_.TakeOwnershipOfSelection(clipboard_data_);
}
-scoped_ptr<SelectionData> Clipboard::AuraX11Details::RequestAndWaitForTypes(
+SelectionData Clipboard::AuraX11Details::RequestAndWaitForTypes(
Buffer buffer,
const std::vector< ::Atom>& types) {
::Atom selection_name = LookupSelectionForBuffer(buffer);
if (XGetSelectionOwner(x_display_, selection_name) == x_window_) {
// We can local fastpath instead of playing the nested message loop game
// with the X server.
- SelectionFormatMap* format_map = LookupStorageForAtom(selection_name);
- DCHECK(format_map);
+ const SelectionFormatMap& format_map = LookupStorageForAtom(selection_name);
for (std::vector< ::Atom>::const_iterator it = types.begin();
it != types.end(); ++it) {
- SelectionFormatMap::const_iterator format_map_it = format_map->find(*it);
- if (format_map_it != format_map->end()) {
- scoped_ptr<SelectionData> data_out(new SelectionData);
- data_out->Set(format_map_it->first, format_map_it->second.first,
- format_map_it->second.second, false);
- return data_out.Pass();
- }
+ SelectionFormatMap::const_iterator format_map_it = format_map.find(*it);
+ if (format_map_it != format_map.end())
+ return SelectionData(format_map_it->first, format_map_it->second);
}
} else {
TargetList targets = WaitAndGetTargetsList(buffer);
@@ -414,7 +408,7 @@ scoped_ptr<SelectionData> Clipboard::AuraX11Details::RequestAndWaitForTypes(
return receiver->RequestAndWaitForTypes(intersection);
}
- return scoped_ptr<SelectionData>();
+ return SelectionData();
}
TargetList Clipboard::AuraX11Details::WaitAndGetTargetsList(
@@ -423,15 +417,14 @@ TargetList Clipboard::AuraX11Details::WaitAndGetTargetsList(
std::vector< ::Atom> out;
if (XGetSelectionOwner(x_display_, selection_name) == x_window_) {
// We can local fastpath and return the list of local targets.
- SelectionFormatMap* format_map = LookupStorageForAtom(selection_name);
- DCHECK(format_map);
+ const SelectionFormatMap& format_map = LookupStorageForAtom(selection_name);
- for (SelectionFormatMap::const_iterator it = format_map->begin();
- it != format_map->end(); ++it) {
+ for (SelectionFormatMap::const_iterator it = format_map.begin();
+ it != format_map.end(); ++it) {
out.push_back(it->first);
}
} else {
- unsigned char* data = NULL;
+ scoped_refptr<base::RefCountedMemory> data;
size_t out_data_items = 0;
::Atom out_type = None;
@@ -441,11 +434,9 @@ TargetList Clipboard::AuraX11Details::WaitAndGetTargetsList(
NULL,
&out_data_items,
&out_type)) {
- ::Atom* atom_array = reinterpret_cast< ::Atom*>(data);
+ const ::Atom* atom_array = reinterpret_cast<const ::Atom*>(data->front());
for (size_t i = 0; i < out_data_items; ++i)
out.push_back(atom_array[i]);
-
- XFree(data);
} else {
// There was no target list. Most Java apps doesn't offer a TARGETS list,
// even though they AWT to. They will offer individual text types if you
@@ -599,22 +590,20 @@ void Clipboard::ReadAvailableTypes(Buffer buffer, std::vector<string16>* types,
types->push_back(UTF8ToUTF16(kMimeTypePNG));
*contains_filenames = false;
- scoped_ptr<SelectionData> data(aurax11_details_->RequestAndWaitForTypes(
+ SelectionData data(aurax11_details_->RequestAndWaitForTypes(
buffer,
aurax11_details_->GetAtomsForFormat(GetWebCustomDataFormatType())));
- if (!data.get())
- return;
-
- ReadCustomDataTypes(data->data(), data->size(), types);
+ if (data.IsValid())
+ ReadCustomDataTypes(data.GetData(), data.GetSize(), types);
}
void Clipboard::ReadText(Buffer buffer, string16* result) const {
DCHECK(CalledOnValidThread());
- scoped_ptr<SelectionData> data(aurax11_details_->RequestAndWaitForTypes(
+ SelectionData data(aurax11_details_->RequestAndWaitForTypes(
buffer, aurax11_details_->GetTextAtoms()));
- if (data.get()) {
- std::string text = data->GetText();
+ if (data.IsValid()) {
+ std::string text = data.GetText();
*result = UTF8ToUTF16(text);
}
}
@@ -622,10 +611,10 @@ void Clipboard::ReadText(Buffer buffer, string16* result) const {
void Clipboard::ReadAsciiText(Buffer buffer, std::string* result) const {
DCHECK(CalledOnValidThread());
- scoped_ptr<SelectionData> data(aurax11_details_->RequestAndWaitForTypes(
+ SelectionData data(aurax11_details_->RequestAndWaitForTypes(
buffer, aurax11_details_->GetTextAtoms()));
- if (data.get())
- result->assign(data->GetText());
+ if (data.IsValid())
+ result->assign(data.GetText());
}
// TODO(estade): handle different charsets.
@@ -642,25 +631,24 @@ void Clipboard::ReadHTML(Buffer buffer,
*fragment_start = 0;
*fragment_end = 0;
- scoped_ptr<SelectionData> data(aurax11_details_->RequestAndWaitForTypes(
+ SelectionData data(aurax11_details_->RequestAndWaitForTypes(
buffer, aurax11_details_->GetAtomsForFormat(GetHtmlFormatType())));
- if (!data.get())
- return;
+ if (data.IsValid()) {
+ *markup = data.GetHtml();
- *markup = data->GetHtml();
-
- *fragment_start = 0;
- DCHECK(markup->length() <= kuint32max);
- *fragment_end = static_cast<uint32>(markup->length());
+ *fragment_start = 0;
+ DCHECK(markup->length() <= kuint32max);
+ *fragment_end = static_cast<uint32>(markup->length());
+ }
}
void Clipboard::ReadRTF(Buffer buffer, std::string* result) const {
DCHECK(CalledOnValidThread());
- scoped_ptr<SelectionData> data(aurax11_details_->RequestAndWaitForTypes(
+ SelectionData data(aurax11_details_->RequestAndWaitForTypes(
buffer, aurax11_details_->GetAtomsForFormat(GetRtfFormatType())));
- if (data.get())
- data->AssignTo(result);
+ if (data.IsValid())
+ data.AssignTo(result);
}
SkBitmap Clipboard::ReadImage(Buffer buffer) const {
@@ -674,13 +662,11 @@ void Clipboard::ReadCustomData(Buffer buffer,
string16* result) const {
DCHECK(CalledOnValidThread());
- scoped_ptr<SelectionData> data(aurax11_details_->RequestAndWaitForTypes(
+ SelectionData data(aurax11_details_->RequestAndWaitForTypes(
buffer,
aurax11_details_->GetAtomsForFormat(GetWebCustomDataFormatType())));
- if (!data.get())
- return;
-
- ReadCustomDataForType(data->data(), data->size(), type, result);
+ if (data.IsValid())
+ ReadCustomDataForType(data.GetData(), data.GetSize(), type, result);
}
void Clipboard::ReadBookmark(string16* title, std::string* url) const {
@@ -692,10 +678,10 @@ void Clipboard::ReadBookmark(string16* title, std::string* url) const {
void Clipboard::ReadData(const FormatType& format, std::string* result) const {
DCHECK(CalledOnValidThread());
- scoped_ptr<SelectionData> data(aurax11_details_->RequestAndWaitForTypes(
+ SelectionData data(aurax11_details_->RequestAndWaitForTypes(
BUFFER_STANDARD, aurax11_details_->GetAtomsForFormat(format)));
- if (data.get())
- data->AssignTo(result);
+ if (data.IsValid())
+ data.AssignTo(result);
}
uint64 Clipboard::GetSequenceNumber(Buffer buffer) {
@@ -707,13 +693,14 @@ uint64 Clipboard::GetSequenceNumber(Buffer buffer) {
}
void Clipboard::WriteText(const char* text_data, size_t text_len) {
- char* data = new char[text_len];
- memcpy(data, text_data, text_len);
+ std::string str(text_data, text_len);
+ scoped_refptr<base::RefCountedMemory> mem(
+ base::RefCountedString::TakeString(&str));
- aurax11_details_->InsertMapping(kMimeTypeText, data, text_len);
- aurax11_details_->InsertMapping(kText, data, text_len);
- aurax11_details_->InsertMapping(kString, data, text_len);
- aurax11_details_->InsertMapping(kUtf8String, data, text_len);
+ aurax11_details_->InsertMapping(kMimeTypeText, mem);
+ aurax11_details_->InsertMapping(kText, mem);
+ aurax11_details_->InsertMapping(kString, mem);
+ aurax11_details_->InsertMapping(kUtf8String, mem);
}
void Clipboard::WriteHTML(const char* markup_data,
@@ -723,16 +710,14 @@ void Clipboard::WriteHTML(const char* markup_data,
// TODO(estade): We need to expand relative links with |url_data|.
static const char* html_prefix = "<meta http-equiv=\"content-type\" "
"content=\"text/html; charset=utf-8\">";
- size_t html_prefix_len = strlen(html_prefix);
- size_t total_len = html_prefix_len + markup_len + 1;
-
- char* data = new char[total_len];
- snprintf(data, total_len, "%s", html_prefix);
- memcpy(data + html_prefix_len, markup_data, markup_len);
+ std::string data = html_prefix;
+ data += std::string(markup_data, markup_len);
// Some programs expect NULL-terminated data. See http://crbug.com/42624
- data[total_len - 1] = '\0';
+ data += '\0';
- aurax11_details_->InsertMapping(kMimeTypeHTML, data, total_len);
+ scoped_refptr<base::RefCountedMemory> mem(
+ base::RefCountedString::TakeString(&data));
+ aurax11_details_->InsertMapping(kMimeTypeHTML, mem);
}
void Clipboard::WriteRTF(const char* rtf_data, size_t data_len) {
@@ -746,18 +731,21 @@ void Clipboard::WriteBookmark(const char* title_data,
// Write as a mozilla url (UTF16: URL, newline, title).
string16 url = UTF8ToUTF16(std::string(url_data, url_len) + "\n");
string16 title = UTF8ToUTF16(std::string(title_data, title_len));
- int data_len = 2 * (title.length() + url.length());
- char* data = new char[data_len];
- memcpy(data, url.data(), 2 * url.length());
- memcpy(data + 2 * url.length(), title.data(), 2 * title.length());
- aurax11_details_->InsertMapping(kMimeTypeMozillaURL, data, data_len);
+ std::vector<unsigned char> data;
+ ui::AddString16ToVector(url, &data);
+ ui::AddString16ToVector(title, &data);
+ scoped_refptr<base::RefCountedMemory> mem(
+ base::RefCountedBytes::TakeVector(&data));
+
+ aurax11_details_->InsertMapping(kMimeTypeMozillaURL, mem);
}
// Write an extra flavor that signifies WebKit was the last to modify the
// pasteboard. This flavor has no data.
void Clipboard::WriteWebSmartPaste() {
- aurax11_details_->InsertMapping(kMimeTypeWebkitSmartPaste, NULL, 0);
+ aurax11_details_->InsertMapping(kMimeTypeWebkitSmartPaste,
+ scoped_refptr<base::RefCountedMemory>());
}
void Clipboard::WriteBitmap(const char* pixel_data, const char* size_data) {
@@ -774,9 +762,11 @@ void Clipboard::WriteData(const FormatType& format,
// Therefore we must upkeep their integrity.
if (format.Equals(GetBitmapFormatType()))
return;
- char* data = new char[data_len];
- memcpy(data, data_data, data_len);
- aurax11_details_->InsertMapping(format.ToString(), data, data_len);
+
+ std::vector<unsigned char> bytes(data_data, data_data + data_len);
+ scoped_refptr<base::RefCountedMemory> mem(
+ base::RefCountedBytes::TakeVector(&bytes));
+ aurax11_details_->InsertMapping(format.ToString(), mem);
}
// static
diff --git a/ui/base/dragdrop/os_exchange_data_provider_aurax11.cc b/ui/base/dragdrop/os_exchange_data_provider_aurax11.cc
index d760a72..7aed8d8 100644
--- a/ui/base/dragdrop/os_exchange_data_provider_aurax11.cc
+++ b/ui/base/dragdrop/os_exchange_data_provider_aurax11.cc
@@ -5,6 +5,7 @@
#include "ui/base/dragdrop/os_exchange_data_provider_aurax11.h"
#include "base/logging.h"
+#include "base/memory/ref_counted_memory.h"
#include "base/message_loop/message_pump_aurax11.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
@@ -40,13 +41,13 @@ const char* kAtomsToCache[] = {
OSExchangeDataProviderAuraX11::OSExchangeDataProviderAuraX11(
::Window x_window,
- scoped_ptr<SelectionFormatMap> selection)
+ const SelectionFormatMap& selection)
: x_display_(GetXDisplay()),
x_root_window_(DefaultRootWindow(x_display_)),
own_window_(false),
x_window_(x_window),
atom_cache_(x_display_, kAtomsToCache),
- format_map_(selection.Pass()),
+ format_map_(selection),
selection_owner_(x_display_, x_window_,
atom_cache_.GetAtom(kDndSelection)) {
// We don't know all possible MIME types at compile time.
@@ -68,7 +69,7 @@ OSExchangeDataProviderAuraX11::OSExchangeDataProviderAuraX11()
0,
NULL)),
atom_cache_(x_display_, kAtomsToCache),
- format_map_(new SelectionFormatMap),
+ format_map_(),
selection_owner_(x_display_, x_window_,
atom_cache_.GetAtom(kDndSelection)) {
// We don't know all possible MIME types at compile time.
@@ -87,8 +88,7 @@ OSExchangeDataProviderAuraX11::~OSExchangeDataProviderAuraX11() {
}
void OSExchangeDataProviderAuraX11::TakeOwnershipOfSelection() const {
- selection_owner_.TakeOwnershipOfSelection(
- scoped_ptr<SelectionFormatMap>(format_map_->Clone()));
+ selection_owner_.TakeOwnershipOfSelection(format_map_);
}
void OSExchangeDataProviderAuraX11::RetrieveTargets(
@@ -96,29 +96,21 @@ void OSExchangeDataProviderAuraX11::RetrieveTargets(
selection_owner_.RetrieveTargets(targets);
}
-scoped_ptr<SelectionFormatMap>
-OSExchangeDataProviderAuraX11::CloneFormatMap() const {
- // We clone the |selection_owner_|'s format map instead of our own in case
+SelectionFormatMap OSExchangeDataProviderAuraX11::GetFormatMap() const {
+ // We return the |selection_owner_|'s format map instead of our own in case
// ours has been modified since TakeOwnershipOfSelection() was called.
- return selection_owner_.selection_format_map()->Clone();
+ return selection_owner_.selection_format_map();
}
void OSExchangeDataProviderAuraX11::SetString(const string16& text_data) {
std::string utf8 = UTF16ToUTF8(text_data);
+ scoped_refptr<base::RefCountedMemory> mem(
+ base::RefCountedString::TakeString(&utf8));
- // Ownership of |data| is passed to |format_map_|.
- size_t text_len = utf8.size();
- char* data = new char[text_len];
- memcpy(data, utf8.c_str(), text_len);
-
- format_map_->Insert(
- atom_cache_.GetAtom(Clipboard::kMimeTypeText), data, text_len);
- format_map_->Insert(
- atom_cache_.GetAtom(kText), data, text_len);
- format_map_->Insert(
- atom_cache_.GetAtom(kString), data, text_len);
- format_map_->Insert(
- atom_cache_.GetAtom(kUtf8String), data, text_len);
+ format_map_.Insert(atom_cache_.GetAtom(Clipboard::kMimeTypeText), mem);
+ format_map_.Insert(atom_cache_.GetAtom(kText), mem);
+ format_map_.Insert(atom_cache_.GetAtom(kString), mem);
+ format_map_.Insert(atom_cache_.GetAtom(kUtf8String), mem);
}
void OSExchangeDataProviderAuraX11::SetURL(const GURL& url,
@@ -146,9 +138,9 @@ bool OSExchangeDataProviderAuraX11::GetString(string16* result) const {
std::vector< ::Atom> requested_types;
ui::GetAtomIntersection(text_atoms, GetTargets(), &requested_types);
- scoped_ptr<ui::SelectionData> data(format_map_->GetFirstOf(requested_types));
- if (data) {
- std::string text = data->GetText();
+ ui::SelectionData data(format_map_.GetFirstOf(requested_types));
+ if (data.IsValid()) {
+ std::string text = data.GetText();
*result = UTF8ToUTF16(text);
return true;
}
@@ -162,16 +154,16 @@ bool OSExchangeDataProviderAuraX11::GetURLAndTitle(GURL* url,
std::vector< ::Atom> requested_types;
ui::GetAtomIntersection(url_atoms, GetTargets(), &requested_types);
- scoped_ptr<ui::SelectionData> data(format_map_->GetFirstOf(requested_types));
- if (data) {
+ ui::SelectionData data(format_map_.GetFirstOf(requested_types));
+ if (data.IsValid()) {
// TODO(erg): Technically, both of these forms can accept multiple URLs,
// but that doesn't match the assumptions of the rest of the system which
// expect single types.
- if (data->type() == atom_cache_.GetAtom(kMimeTypeMozillaURL)) {
+ if (data.GetType() == atom_cache_.GetAtom(kMimeTypeMozillaURL)) {
// Mozilla URLs are (UTF16: URL, newline, title).
string16 unparsed;
- data->AssignTo(&unparsed);
+ data.AssignTo(&unparsed);
std::vector<string16> tokens;
size_t num_tokens = Tokenize(unparsed, ASCIIToUTF16("\n"), &tokens);
@@ -183,11 +175,11 @@ bool OSExchangeDataProviderAuraX11::GetURLAndTitle(GURL* url,
NOTREACHED() << "Data that claimed to be a Mozilla URL has "
<< num_tokens << " tokens instead of 2.";
}
- } else if (data->type() == atom_cache_.GetAtom(
+ } else if (data.GetType() == atom_cache_.GetAtom(
Clipboard::kMimeTypeURIList)) {
// uri-lists are newline separated file lists in URL encoding.
std::string unparsed;
- data->AssignTo(&unparsed);
+ data.AssignTo(&unparsed);
std::vector<std::string> tokens;
size_t num_tokens = Tokenize(unparsed, "\n", &tokens);
@@ -265,9 +257,9 @@ bool OSExchangeDataProviderAuraX11::GetHtml(string16* html,
std::vector< ::Atom> requested_types;
ui::GetAtomIntersection(url_atoms, GetTargets(), &requested_types);
- scoped_ptr<ui::SelectionData> data(format_map_->GetFirstOf(requested_types));
- if (data) {
- *html = data->GetHtml();
+ ui::SelectionData data(format_map_.GetFirstOf(requested_types));
+ if (data.IsValid()) {
+ *html = data.GetHtml();
*base_url = GURL();
return true;
}
@@ -318,7 +310,7 @@ bool OSExchangeDataProviderAuraX11::GetPlainTextURL(GURL* url) const {
}
std::vector< ::Atom> OSExchangeDataProviderAuraX11::GetTargets() const {
- return format_map_->GetTypes();
+ return format_map_.GetTypes();
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/ui/base/dragdrop/os_exchange_data_provider_aurax11.h b/ui/base/dragdrop/os_exchange_data_provider_aurax11.h
index ea41131..09568e2 100644
--- a/ui/base/dragdrop/os_exchange_data_provider_aurax11.h
+++ b/ui/base/dragdrop/os_exchange_data_provider_aurax11.h
@@ -19,6 +19,7 @@
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/base/x/selection_owner.h"
#include "ui/base/x/selection_requestor.h"
+#include "ui/base/x/selection_utils.h"
#include "ui/base/x/x11_atom_cache.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/vector2d.h"
@@ -35,7 +36,7 @@ class UI_EXPORT OSExchangeDataProviderAuraX11
// |x_window| is the window the cursor is over, and |selection| is the set of
// data being offered.
OSExchangeDataProviderAuraX11(::Window x_window,
- scoped_ptr<SelectionFormatMap> selection);
+ const SelectionFormatMap& selection);
// Creates a Provider for sending drag information. This creates its own,
// hidden X11 window to own send data.
@@ -52,7 +53,7 @@ class UI_EXPORT OSExchangeDataProviderAuraX11
void RetrieveTargets(std::vector<Atom>* targets) const;
// Makes a copy of the format map currently being offered.
- scoped_ptr<SelectionFormatMap> CloneFormatMap() const;
+ SelectionFormatMap GetFormatMap() const;
// Overridden from OSExchangeData::Provider:
virtual void SetString(const string16& data) OVERRIDE;
@@ -119,7 +120,7 @@ class UI_EXPORT OSExchangeDataProviderAuraX11
// A representation of data. This is either passed to us from the other
// process, or built up through a sequence of Set*() calls. It can be passed
// to |selection_owner_| when we take the selection.
- scoped_ptr<SelectionFormatMap> format_map_;
+ SelectionFormatMap format_map_;
// Takes a snapshot of |format_map_| and offers it to other windows.
mutable SelectionOwner selection_owner_;
diff --git a/ui/base/x/selection_owner.cc b/ui/base/x/selection_owner.cc
index a5b0f4e..54f59a1 100644
--- a/ui/base/x/selection_owner.cc
+++ b/ui/base/x/selection_owner.cc
@@ -40,19 +40,19 @@ SelectionOwner::~SelectionOwner() {
void SelectionOwner::RetrieveTargets(std::vector<Atom>* targets) {
targets->clear();
- for (SelectionFormatMap::const_iterator it = selection_data_->begin();
- it != selection_data_->end(); ++it) {
+ for (SelectionFormatMap::const_iterator it = format_map_.begin();
+ it != format_map_.end(); ++it) {
targets->push_back(it->first);
}
}
void SelectionOwner::TakeOwnershipOfSelection(
- scoped_ptr<SelectionFormatMap> data) {
+ const SelectionFormatMap& data) {
XSetSelectionOwner(x_display_, selection_name_, x_window_, CurrentTime);
if (XGetSelectionOwner(x_display_, selection_name_) == x_window_) {
// The X server agrees that we are the selection owner. Commit our data.
- selection_data_ = data.Pass();
+ format_map_ = data;
}
}
@@ -60,7 +60,7 @@ void SelectionOwner::Clear() {
if (XGetSelectionOwner(x_display_, selection_name_) == x_window_)
XSetSelectionOwner(x_display_, selection_name_, None, CurrentTime);
- selection_data_.reset();
+ format_map_ = SelectionFormatMap();
}
void SelectionOwner::OnSelectionRequest(const XSelectionRequestEvent& event) {
@@ -75,42 +75,39 @@ void SelectionOwner::OnSelectionRequest(const XSelectionRequestEvent& event) {
reply.xselection.time = event.time;
// Get the proper selection.
- if (selection_data_.get()) {
- Atom targets_atom = atom_cache_.GetAtom(kTargets);
- if (event.target == targets_atom) {
- // We have been asked for TARGETS. Send an atom array back with the data
- // types we support.
- std::vector<Atom> targets;
- targets.push_back(targets_atom);
- RetrieveTargets(&targets);
-
- XChangeProperty(x_display_, event.requestor, event.property, XA_ATOM, 32,
+ Atom targets_atom = atom_cache_.GetAtom(kTargets);
+ if (event.target == targets_atom) {
+ // We have been asked for TARGETS. Send an atom array back with the data
+ // types we support.
+ std::vector<Atom> targets;
+ targets.push_back(targets_atom);
+ RetrieveTargets(&targets);
+
+ XChangeProperty(x_display_, event.requestor, event.property, XA_ATOM, 32,
+ PropModeReplace,
+ reinterpret_cast<unsigned char*>(&targets.front()),
+ targets.size());
+ reply.xselection.property = event.property;
+ } else if (event.target == atom_cache_.GetAtom(kMultiple)) {
+ // TODO(erg): Theoretically, the spec claims I'm supposed to handle the
+ // MULTIPLE case, but I haven't seen it in the wild yet.
+ NOTIMPLEMENTED();
+ } else {
+ // Try to find the data type in map.
+ SelectionFormatMap::const_iterator it =
+ format_map_.find(event.target);
+ if (it != format_map_.end()) {
+ XChangeProperty(x_display_, event.requestor, event.property,
+ event.target, 8,
PropModeReplace,
- reinterpret_cast<unsigned char*>(&targets.front()),
- targets.size());
+ const_cast<unsigned char*>(
+ reinterpret_cast<const unsigned char*>(
+ it->second->front())),
+ it->second->size());
reply.xselection.property = event.property;
- } else if (event.target == atom_cache_.GetAtom(kMultiple)) {
- // TODO(erg): Theoretically, the spec claims I'm supposed to handle the
- // MULTIPLE case, but I haven't seen it in the wild yet.
- NOTIMPLEMENTED();
- } else {
- // Try to find the data type in map.
- SelectionFormatMap::const_iterator it =
- selection_data_->find(event.target);
- if (it != selection_data_->end()) {
- XChangeProperty(x_display_, event.requestor, event.property,
- event.target, 8,
- PropModeReplace,
- reinterpret_cast<unsigned char*>(it->second.first),
- it->second.second);
- reply.xselection.property = event.property;
- }
- // I would put error logging here, but GTK ignores TARGETS and spams us
- // looking for its own internal types.
}
- } else {
- DLOG(ERROR) << "XWindow " << x_window_ << " received a SelectionRequest "
- << "message when we don't have data to offer.";
+ // I would put error logging here, but GTK ignores TARGETS and spams us
+ // looking for its own internal types.
}
// Send off the reply.
diff --git a/ui/base/x/selection_owner.h b/ui/base/x/selection_owner.h
index a62be52..6c5c7f8 100644
--- a/ui/base/x/selection_owner.h
+++ b/ui/base/x/selection_owner.h
@@ -15,12 +15,11 @@
#include "base/basictypes.h"
#include "base/callback.h"
#include "ui/base/ui_export.h"
+#include "ui/base/x/selection_utils.h"
#include "ui/base/x/x11_atom_cache.h"
namespace ui {
-class SelectionFormatMap;
-
// Owns a specific X11 selection on an X window.
//
// The selection owner object keeps track of which xwindow is the current
@@ -34,14 +33,14 @@ class UI_EXPORT SelectionOwner {
~SelectionOwner();
// Returns the current selection data. Useful for fast paths.
- SelectionFormatMap* selection_format_map() { return selection_data_.get(); }
+ const SelectionFormatMap& selection_format_map() { return format_map_; }
// Retrieves a list of types we're offering.
void RetrieveTargets(std::vector<Atom>* targets);
// Attempts to take ownership of the selection. If we're successful, present
// |data| to other windows.
- void TakeOwnershipOfSelection(scoped_ptr<SelectionFormatMap> data);
+ void TakeOwnershipOfSelection(const SelectionFormatMap& data);
// Releases the selection (if we own it) and clears any data we own.
void Clear();
@@ -61,7 +60,7 @@ class UI_EXPORT SelectionOwner {
::Atom selection_name_;
// The data we are currently serving.
- scoped_ptr<SelectionFormatMap> selection_data_;
+ SelectionFormatMap format_map_;
X11AtomCache atom_cache_;
diff --git a/ui/base/x/selection_requestor.cc b/ui/base/x/selection_requestor.cc
index 1fd2872..405c059 100644
--- a/ui/base/x/selection_requestor.cc
+++ b/ui/base/x/selection_requestor.cc
@@ -38,7 +38,7 @@ SelectionRequestor::~SelectionRequestor() {}
bool SelectionRequestor::PerformBlockingConvertSelection(
Atom target,
- unsigned char** out_data,
+ scoped_refptr<base::RefCountedMemory>* out_data,
size_t* out_data_bytes,
size_t* out_data_items,
Atom* out_type) {
@@ -73,11 +73,11 @@ bool SelectionRequestor::PerformBlockingConvertSelection(
out_type);
}
-scoped_ptr<SelectionData> SelectionRequestor::RequestAndWaitForTypes(
+SelectionData SelectionRequestor::RequestAndWaitForTypes(
const std::vector< ::Atom>& types) {
for (std::vector< ::Atom>::const_iterator it = types.begin();
it != types.end(); ++it) {
- unsigned char* data = NULL;
+ scoped_refptr<base::RefCountedMemory> data;
size_t data_bytes = 0;
::Atom type = None;
if (PerformBlockingConvertSelection(*it,
@@ -86,13 +86,11 @@ scoped_ptr<SelectionData> SelectionRequestor::RequestAndWaitForTypes(
NULL,
&type) &&
type == *it) {
- scoped_ptr<SelectionData> data_out(new SelectionData);
- data_out->Set(type, (char*)data, data_bytes, true);
- return data_out.Pass();
+ return SelectionData(type, data);
}
}
- return scoped_ptr<SelectionData>();
+ return SelectionData();
}
void SelectionRequestor::OnSelectionNotify(const XSelectionEvent& event) {
diff --git a/ui/base/x/selection_requestor.h b/ui/base/x/selection_requestor.h
index 52ad1cf..318533a 100644
--- a/ui/base/x/selection_requestor.h
+++ b/ui/base/x/selection_requestor.h
@@ -14,6 +14,7 @@
#include "base/basictypes.h"
#include "base/callback.h"
+#include "base/memory/ref_counted_memory.h"
#include "ui/base/ui_export.h"
#include "ui/base/x/x11_atom_cache.h"
@@ -39,16 +40,16 @@ class UI_EXPORT SelectionRequestor {
// back. |out_data| is allocated with the X allocator and must be freed with
// XFree(). |out_data_bytes| is the length in machine chars, while
// |out_data_items| is the length in |out_type| items.
- bool PerformBlockingConvertSelection(::Atom target,
- unsigned char** out_data,
- size_t* out_data_bytes,
- size_t* out_data_items,
- ::Atom* out_type);
+ bool PerformBlockingConvertSelection(
+ ::Atom target,
+ scoped_refptr<base::RefCountedMemory>* out_data,
+ size_t* out_data_bytes,
+ size_t* out_data_items,
+ ::Atom* out_type);
// Returns the first of |types| offered by the current selection holder, or
// returns NULL if none of those types are available.
- scoped_ptr<SelectionData> RequestAndWaitForTypes(
- const std::vector< ::Atom>& types);
+ SelectionData RequestAndWaitForTypes(const std::vector< ::Atom>& types);
// It is our owner's responsibility to plumb X11 SelectionNotify events on
// |xwindow_| to us.
diff --git a/ui/base/x/selection_utils.cc b/ui/base/x/selection_utils.cc
index 5dd6f68..560f494 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
diff --git a/ui/base/x/selection_utils.h b/ui/base/x/selection_utils.h
index d7abf3f..609ee9d 100644
--- a/ui/base/x/selection_utils.h
+++ b/ui/base/x/selection_utils.h
@@ -13,6 +13,7 @@
#include <map>
#include "base/basictypes.h"
+#include "base/memory/ref_counted_memory.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/ui_export.h"
#include "ui/base/x/x11_atom_cache.h"
@@ -36,6 +37,16 @@ UI_EXPORT void GetAtomIntersection(const std::vector< ::Atom>& one,
const std::vector< ::Atom>& two,
std::vector< ::Atom>* output);
+// Takes the raw bytes of the string16 and copies them into |bytes|.
+UI_EXPORT void AddString16ToVector(const string16& str,
+ std::vector<unsigned char>* bytes);
+
+UI_EXPORT std::string RefCountedMemoryToString(
+ const scoped_refptr<base::RefCountedMemory>& memory);
+
+UI_EXPORT string16 RefCountedMemoryToString16(
+ const scoped_refptr<base::RefCountedMemory>& memory);
+
///////////////////////////////////////////////////////////////////////////////
// Represents the selection in different data formats. Binary data passed in is
@@ -43,27 +54,24 @@ UI_EXPORT void GetAtomIntersection(const std::vector< ::Atom>& one,
class UI_EXPORT SelectionFormatMap {
public:
// Our internal data store, which we only expose through iterators.
- typedef std::map< ::Atom, std::pair<char*, size_t> > InternalMap;
- typedef std::map< ::Atom, std::pair<char*, size_t> >::const_iterator
- const_iterator;
+ typedef std::map< ::Atom, scoped_refptr<base::RefCountedMemory> > InternalMap;
+ typedef InternalMap::const_iterator const_iterator;
SelectionFormatMap();
~SelectionFormatMap();
+ // Copy and assignment deliberately open.
// Adds the selection in the format |atom|. Ownership of |data| is passed to
// us.
- void Insert(::Atom atom, char* data, size_t size);
+ void Insert(::Atom atom, const scoped_refptr<base::RefCountedMemory>& item);
// Returns the first of the requested_types or NULL if missing.
- ui::SelectionData* GetFirstOf(
+ ui::SelectionData GetFirstOf(
const std::vector< ::Atom>& requested_types) const;
// Returns all the selected types.
std::vector< ::Atom> GetTypes() const;
- // Creates a copy of the selection data.
- scoped_ptr<SelectionFormatMap> Clone() const;
-
// Pass through to STL map. Only allow non-mutation access.
const_iterator begin() const { return data_.begin(); }
const_iterator end() const { return data_.end(); }
@@ -72,8 +80,6 @@ class UI_EXPORT SelectionFormatMap {
private:
InternalMap data_;
-
- DISALLOW_COPY_AND_ASSIGN(SelectionFormatMap);
};
///////////////////////////////////////////////////////////////////////////////
@@ -83,13 +89,16 @@ class UI_EXPORT SelectionData {
public:
// |atom_cache| is still owned by caller.
SelectionData();
+ SelectionData(::Atom type,
+ const scoped_refptr<base::RefCountedMemory>& memory);
+ SelectionData(const SelectionData& rhs);
~SelectionData();
+ SelectionData& operator=(const SelectionData& rhs);
- ::Atom type() const { return type_; }
- char* data() const { return data_; }
- size_t size() const { return size_; }
-
- void Set(::Atom type, char* data, size_t size, bool owned);
+ bool IsValid() const;
+ ::Atom GetType() const;
+ const unsigned char* GetData() const;
+ size_t GetSize() const;
// If |type_| is a string type, convert the data to UTF8 and return it.
std::string GetText() const;
@@ -104,13 +113,9 @@ class UI_EXPORT SelectionData {
private:
::Atom type_;
- char* data_;
- size_t size_;
- bool owned_;
+ scoped_refptr<base::RefCountedMemory> memory_;
X11AtomCache atom_cache_;
-
- DISALLOW_COPY_AND_ASSIGN(SelectionData);
};
} // namespace ui
diff --git a/ui/base/x/x11_util.cc b/ui/base/x/x11_util.cc
index 1ac4513..324cdd13 100644
--- a/ui/base/x/x11_util.cc
+++ b/ui/base/x/x11_util.cc
@@ -763,7 +763,7 @@ bool PropertyExists(XID window, const std::string& property_name) {
bool GetRawBytesOfProperty(XID window,
Atom property,
- unsigned char** out_data,
+ scoped_refptr<base::RefCountedMemory>* out_data,
size_t* out_data_bytes,
size_t* out_data_items,
Atom* out_type) {
@@ -783,31 +783,33 @@ bool GetRawBytesOfProperty(XID window,
if (prop_type == None)
return false;
+ size_t bytes = 0;
+ // So even though we should theoretically have nbytes (and we can't
+ // pass NULL there), we need to manually calculate the byte length here
+ // because nbytes always returns zero.
+ switch (prop_format) {
+ case 8:
+ bytes = nitems;
+ break;
+ case 16:
+ bytes = sizeof(short) * nitems;
+ break;
+ case 32:
+ bytes = sizeof(long) * nitems;
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+
+ if (out_data_bytes)
+ *out_data_bytes = bytes;
+
if (out_data)
- *out_data = property_data;
+ *out_data = new XRefcountedMemory(property_data, bytes);
else
XFree(property_data);
- if (out_data_bytes) {
- // So even though we should theoretically have nbytes (and we can't
- // pass NULL there), we need to manually calculate the byte length here
- // because nbytes always returns zero.
- switch (prop_format) {
- case 8:
- *out_data_bytes = nitems;
- break;
- case 16:
- *out_data_bytes = sizeof(short) * nitems;
- break;
- case 32:
- *out_data_bytes = sizeof(long) * nitems;
- break;
- default:
- NOTREACHED();
- break;
- }
- }
-
if (out_data_items)
*out_data_items = nitems;
@@ -1501,6 +1503,18 @@ void InitXKeyEventForTesting(EventType type,
event->xkey = key_event;
}
+const unsigned char* XRefcountedMemory::front() const {
+ return x11_data_;
+}
+
+size_t XRefcountedMemory::size() const {
+ return length_;
+}
+
+XRefcountedMemory::~XRefcountedMemory() {
+ XFree(x11_data_);
+}
+
XScopedString::~XScopedString() {
XFree(string_);
}
diff --git a/ui/base/x/x11_util.h b/ui/base/x/x11_util.h
index 592e48a..c1c72ba 100644
--- a/ui/base/x/x11_util.h
+++ b/ui/base/x/x11_util.h
@@ -16,6 +16,7 @@
#include "base/basictypes.h"
#include "base/event_types.h"
+#include "base/memory/ref_counted_memory.h"
#include "ui/base/events/event_constants.h"
#include "ui/base/keycodes/keyboard_codes.h"
#include "ui/base/ui_export.h"
@@ -166,12 +167,13 @@ UI_EXPORT bool PropertyExists(XID window, const std::string& property_name);
// Returns the raw bytes from a property with minimal
// interpretation. |out_data| should be freed by XFree() after use.
-UI_EXPORT bool GetRawBytesOfProperty(XID window,
- Atom property,
- unsigned char** out_data,
- size_t* out_data_bytes,
- size_t* out_data_items,
- Atom* out_type);
+UI_EXPORT bool GetRawBytesOfProperty(
+ XID window,
+ Atom property,
+ scoped_refptr<base::RefCountedMemory>* out_data,
+ size_t* out_data_bytes,
+ size_t* out_data_items,
+ Atom* out_type);
// Get the value of an int, int array, atom array or string property. On
// success, true is returned and the value is stored in |value|.
@@ -333,6 +335,29 @@ UI_EXPORT void InitXKeyEventForTesting(EventType type,
int flags,
XEvent* event);
+// Manages a piece of X11 allocated memory as a RefCountedMemory segment. This
+// object takes ownership over the passed in memory and will free it with the
+// X11 allocator when done.
+class UI_EXPORT XRefcountedMemory : public base::RefCountedMemory {
+ public:
+ XRefcountedMemory(unsigned char* x11_data, size_t length)
+ : x11_data_(length ? x11_data : NULL),
+ length_(length) {
+ }
+
+ // Overridden from RefCountedMemory:
+ virtual const unsigned char* front() const OVERRIDE;
+ virtual size_t size() const OVERRIDE;
+
+ private:
+ virtual ~XRefcountedMemory();
+
+ unsigned char* x11_data_;
+ size_t length_;
+
+ DISALLOW_COPY_AND_ASSIGN(XRefcountedMemory);
+};
+
// Keeps track of a string returned by an X function (e.g. XGetAtomName) and
// makes sure it's XFree'd.
class UI_EXPORT XScopedString {
diff --git a/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc b/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc
index 004c19c..953e2d7 100644
--- a/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc
+++ b/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc
@@ -159,10 +159,7 @@ class DesktopDragDropClientAuraX11::X11DragContext :
void OnSelectionNotify(const XSelectionEvent& xselection);
// Clones the fetched targets.
- scoped_ptr<ui::SelectionFormatMap> CloneFetchedTargets() {
- DCHECK(fetched_targets_);
- return fetched_targets_->Clone();
- }
+ const ui::SelectionFormatMap& fetched_targets() { return fetched_targets_; }
// Reads the "XdndActionList" property from |source_window| and copies it
// into |actions|.
@@ -196,7 +193,7 @@ class DesktopDragDropClientAuraX11::X11DragContext :
gfx::Point screen_point_;
// A SelectionFormatMap of data that we have in our process.
- scoped_ptr<ui::SelectionFormatMap> fetched_targets_;
+ ui::SelectionFormatMap fetched_targets_;
// The names of various data types offered by the other window that we
// haven't fetched and put in |fetched_targets_| yet.
@@ -251,7 +248,7 @@ DesktopDragDropClientAuraX11::X11DragContext::X11DragContext(
// This drag originates from an aura window within our process. This means
// that we can shortcut the X11 server and ask the owning SelectionOwner
// for the data it's offering.
- fetched_targets_ = client->CloneFormatMap();
+ fetched_targets_ = client->GetFormatMap();
unfetched_targets_.clear();
}
@@ -281,7 +278,7 @@ void DesktopDragDropClientAuraX11::X11DragContext::OnStartXdndPositionMessage(
drag_drop_client_ = client;
waiting_to_handle_position_ = true;
- fetched_targets_.reset(new ui::SelectionFormatMap);
+ fetched_targets_ = ui::SelectionFormatMap();
RequestNextTarget();
} else {
client->CompleteXdndPosition(source_window, screen_point);
@@ -306,15 +303,11 @@ void DesktopDragDropClientAuraX11::X11DragContext::OnSelectionNotify(
DCHECK(drag_drop_client_);
DCHECK_EQ(event.property, atom_cache_->GetAtom(kChromiumDragReciever));
- unsigned char* data = NULL;
- size_t data_bytes = 0;
+ scoped_refptr<base::RefCountedMemory> data;
::Atom type = None;
if (ui::GetRawBytesOfProperty(local_window_, event.property,
- &data, &data_bytes, NULL, &type)) {
- char* copied_data = new char[data_bytes];
- memcpy(copied_data, data, data_bytes);
- fetched_targets_->Insert(event.target, copied_data, data_bytes);
- XFree(data);
+ &data, NULL, NULL, &type)) {
+ fetched_targets_.Insert(event.target, data);
}
if (!unfetched_targets_.empty()) {
@@ -517,7 +510,7 @@ void DesktopDragDropClientAuraX11::OnXdndDrop(
aura::client::GetDragDropDelegate(target_window_);
if (delegate) {
ui::OSExchangeData data(new ui::OSExchangeDataProviderAuraX11(
- xwindow_, target_current_context_->CloneFetchedTargets()));
+ xwindow_, target_current_context_->fetched_targets()));
ui::DropTargetEvent event(data,
target_window_location_,
@@ -693,7 +686,7 @@ void DesktopDragDropClientAuraX11::DragTranslate(
return;
data->reset(new OSExchangeData(new ui::OSExchangeDataProviderAuraX11(
- xwindow_, target_current_context_->CloneFetchedTargets())));
+ xwindow_, target_current_context_->fetched_targets())));
gfx::Point location = root_location;
aura::Window::ConvertPointToTarget(root_window_, target_window_, &location);
@@ -754,10 +747,9 @@ std::vector< ::Atom> DesktopDragDropClientAuraX11::GetOfferedDragOperations() {
return operations;
}
-scoped_ptr<ui::SelectionFormatMap>
-DesktopDragDropClientAuraX11::CloneFormatMap() const {
- return source_provider_ ? source_provider_->CloneFormatMap() :
- scoped_ptr<ui::SelectionFormatMap>();
+ui::SelectionFormatMap DesktopDragDropClientAuraX11::GetFormatMap() const {
+ return source_provider_ ? source_provider_->GetFormatMap() :
+ ui::SelectionFormatMap();
}
void DesktopDragDropClientAuraX11::CompleteXdndPosition(
diff --git a/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h b/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h
index 4152778..47b82061 100644
--- a/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h
+++ b/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h
@@ -128,10 +128,10 @@ class VIEWS_EXPORT DesktopDragDropClientAuraX11
// processes.
std::vector< ::Atom> GetOfferedDragOperations();
- // This returns a newly allocated copy of the data we're offering in this
+ // This returns a representation of the data we're offering in this
// drag. This is done to bypass an asynchronous roundtrip with the X11
// server.
- scoped_ptr<ui::SelectionFormatMap> CloneFormatMap() const;
+ ui::SelectionFormatMap GetFormatMap() const;
// Handling XdndPosition can be paused while waiting for more data; this is
// called either synchronously from OnXdndPosition, or asynchronously after