diff options
-rw-r--r-- | ui/base/clipboard/clipboard_aurax11.cc | 174 | ||||
-rw-r--r-- | ui/base/dragdrop/os_exchange_data_provider_aurax11.cc | 62 | ||||
-rw-r--r-- | ui/base/dragdrop/os_exchange_data_provider_aurax11.h | 7 | ||||
-rw-r--r-- | ui/base/x/selection_owner.cc | 73 | ||||
-rw-r--r-- | ui/base/x/selection_owner.h | 9 | ||||
-rw-r--r-- | ui/base/x/selection_requestor.cc | 12 | ||||
-rw-r--r-- | ui/base/x/selection_requestor.h | 15 | ||||
-rw-r--r-- | ui/base/x/selection_utils.cc | 155 | ||||
-rw-r--r-- | ui/base/x/selection_utils.h | 45 | ||||
-rw-r--r-- | ui/base/x/x11_util.cc | 58 | ||||
-rw-r--r-- | ui/base/x/x11_util.h | 37 | ||||
-rw-r--r-- | ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc | 32 | ||||
-rw-r--r-- | ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h | 4 |
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 |