1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/base/dragdrop/os_exchange_data_provider_aurax11.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/logging.h"
8eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/memory/ref_counted_memory.h"
95e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h"
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
11c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "net/base/filename_util.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/base/clipboard/clipboard.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/base/clipboard/scoped_clipboard_writer.h"
14effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "ui/base/dragdrop/file_info.h"
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/base/x/selection_utils.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/base/x/x11_util.h"
17c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "ui/events/platform/platform_event_source.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Note: the GetBlah() methods are used immediately by the
20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// web_contents_view_aura.cc:PrepareDropData(), while the omnibox is a
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// little more discriminating and calls HasBlah() before trying to get the
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// information.
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace ui {
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace {
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kDndSelection[] = "XdndSelection";
29effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochconst char kRendererTaint[] = "chromium/x-renderer-taint";
30effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
31effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochconst char kNetscapeURL[] = "_NETSCAPE_URL";
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char* kAtomsToCache[] = {
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  kString,
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  kText,
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  kUtf8String,
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  kDndSelection,
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Clipboard::kMimeTypeURIList,
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  kMimeTypeMozillaURL,
40effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  kNetscapeURL,
41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  Clipboard::kMimeTypeText,
42effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  kRendererTaint,
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  NULL
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)OSExchangeDataProviderAuraX11::OSExchangeDataProviderAuraX11(
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ::Window x_window,
50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const SelectionFormatMap& selection)
5168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    : x_display_(gfx::GetXDisplay()),
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      x_root_window_(DefaultRootWindow(x_display_)),
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      own_window_(false),
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      x_window_(x_window),
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      atom_cache_(x_display_, kAtomsToCache),
56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      format_map_(selection),
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      selection_owner_(x_display_, x_window_,
58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                       atom_cache_.GetAtom(kDndSelection)) {
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // We don't know all possible MIME types at compile time.
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  atom_cache_.allow_uncached_atoms();
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)OSExchangeDataProviderAuraX11::OSExchangeDataProviderAuraX11()
6468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    : x_display_(gfx::GetXDisplay()),
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      x_root_window_(DefaultRootWindow(x_display_)),
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      own_window_(true),
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      x_window_(XCreateWindow(
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          x_display_,
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          x_root_window_,
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          -100, -100, 10, 10,  // x, y, width, height
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          0,                   // border width
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          CopyFromParent,      // depth
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          InputOnly,
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          CopyFromParent,      // visual
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          0,
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          NULL)),
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      atom_cache_(x_display_, kAtomsToCache),
78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      format_map_(),
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      selection_owner_(x_display_, x_window_,
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       atom_cache_.GetAtom(kDndSelection)) {
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // We don't know all possible MIME types at compile time.
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  atom_cache_.allow_uncached_atoms();
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  XStoreName(x_display_, x_window_, "Chromium Drag & Drop Window");
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
86c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this);
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)OSExchangeDataProviderAuraX11::~OSExchangeDataProviderAuraX11() {
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (own_window_) {
91c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this);
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    XDestroyWindow(x_display_, x_window_);
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
96eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid OSExchangeDataProviderAuraX11::TakeOwnershipOfSelection() const {
97eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  selection_owner_.TakeOwnershipOfSelection(format_map_);
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid OSExchangeDataProviderAuraX11::RetrieveTargets(
101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    std::vector<Atom>* targets) const {
102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  selection_owner_.RetrieveTargets(targets);
103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochSelectionFormatMap OSExchangeDataProviderAuraX11::GetFormatMap() const {
106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // We return the |selection_owner_|'s format map instead of our own in case
107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // ours has been modified since TakeOwnershipOfSelection() was called.
108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return selection_owner_.selection_format_map();
109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochOSExchangeData::Provider* OSExchangeDataProviderAuraX11::Clone() const {
112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OSExchangeDataProviderAuraX11* ret = new OSExchangeDataProviderAuraX11();
113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ret->format_map_ = format_map_;
114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return ret;
115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
117effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid OSExchangeDataProviderAuraX11::MarkOriginatedFromRenderer() {
118effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  std::string empty;
119effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  format_map_.Insert(atom_cache_.GetAtom(kRendererTaint),
120effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                     scoped_refptr<base::RefCountedMemory>(
121effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                         base::RefCountedString::TakeString(&empty)));
122effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
123effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
124effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool OSExchangeDataProviderAuraX11::DidOriginateFromRenderer() const {
125effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return format_map_.find(atom_cache_.GetAtom(kRendererTaint)) !=
126effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch         format_map_.end();
127effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
128effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid OSExchangeDataProviderAuraX11::SetString(const base::string16& text_data) {
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string utf8 = base::UTF16ToUTF8(text_data);
131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<base::RefCountedMemory> mem(
132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      base::RefCountedString::TakeString(&utf8));
133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  format_map_.Insert(atom_cache_.GetAtom(Clipboard::kMimeTypeText), mem);
135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  format_map_.Insert(atom_cache_.GetAtom(kText), mem);
136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  format_map_.Insert(atom_cache_.GetAtom(kString), mem);
137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  format_map_.Insert(atom_cache_.GetAtom(kUtf8String), mem);
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void OSExchangeDataProviderAuraX11::SetURL(const GURL& url,
141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           const base::string16& title) {
142effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // TODO(dcheng): The original GTK code tries very hard to avoid writing out an
143effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // empty title. Is this necessary?
144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (url.is_valid()) {
145effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // Mozilla's URL format: (UTF16: URL, newline, title)
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::string16 spec = base::UTF8ToUTF16(url.spec());
147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    std::vector<unsigned char> data;
149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    ui::AddString16ToVector(spec, &data);
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ui::AddString16ToVector(base::ASCIIToUTF16("\n"), &data);
151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    ui::AddString16ToVector(title, &data);
152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<base::RefCountedMemory> mem(
153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        base::RefCountedBytes::TakeVector(&data));
154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    format_map_.Insert(atom_cache_.GetAtom(kMimeTypeMozillaURL), mem);
156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
157a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // Set a string fallback as well.
158a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    SetString(spec);
159a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
160a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // Return early if this drag already contains file contents (this implies
161a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // that file contents must be populated before URLs). Nautilus (and possibly
162a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // other file managers) prefer _NETSCAPE_URL over the X Direct Save
163a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // protocol, but we want to prioritize XDS in this case.
164a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    if (!file_contents_name_.empty())
165a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      return;
166a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
167a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // Set _NETSCAPE_URL for file managers like Nautilus that use it as a hint
168a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // to create a link to the URL. Setting text/uri-list doesn't work because
169a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // Nautilus will fetch and copy the contents of the URL to the drop target
170a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // instead of linking...
171effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // Format is UTF8: URL + "\n" + title.
172effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    std::string netscape_url = url.spec();
173effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    netscape_url += "\n";
174effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    netscape_url += base::UTF16ToUTF8(title);
175effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    format_map_.Insert(atom_cache_.GetAtom(kNetscapeURL),
176effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                       scoped_refptr<base::RefCountedMemory>(
177effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                           base::RefCountedString::TakeString(&netscape_url)));
178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void OSExchangeDataProviderAuraX11::SetFilename(const base::FilePath& path) {
182effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  std::vector<FileInfo> data;
183effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  data.push_back(FileInfo(path, base::FilePath()));
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetFilenames(data);
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void OSExchangeDataProviderAuraX11::SetFilenames(
188effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const std::vector<FileInfo>& filenames) {
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::vector<std::string> paths;
190effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  for (std::vector<FileInfo>::const_iterator it = filenames.begin();
191effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch       it != filenames.end();
192effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch       ++it) {
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::string url_spec = net::FilePathToFileURL(it->path).spec();
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!url_spec.empty())
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      paths.push_back(url_spec);
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string joined_data = JoinString(paths, '\n');
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<base::RefCountedMemory> mem(
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::RefCountedString::TakeString(&joined_data));
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  format_map_.Insert(atom_cache_.GetAtom(Clipboard::kMimeTypeURIList), mem);
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void OSExchangeDataProviderAuraX11::SetPickledData(
20590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const OSExchangeData::CustomFormat& format,
206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const Pickle& pickle) {
207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const unsigned char* data =
208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      reinterpret_cast<const unsigned char*>(pickle.data());
209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::vector<unsigned char> bytes;
211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bytes.insert(bytes.end(), data, data + pickle.size());
212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<base::RefCountedMemory> mem(
213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      base::RefCountedBytes::TakeVector(&bytes));
214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  format_map_.Insert(atom_cache_.GetAtom(format.ToString().c_str()), mem);
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool OSExchangeDataProviderAuraX11::GetString(base::string16* result) const {
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (HasFile()) {
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Various Linux file managers both pass a list of file:// URIs and set the
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // string representation to the URI. We explicitly don't want to return use
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // this representation.
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::vector< ::Atom> text_atoms = ui::GetTextAtomsFrom(&atom_cache_);
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::vector< ::Atom> requested_types;
228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ui::GetAtomIntersection(text_atoms, GetTargets(), &requested_types);
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
230eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ui::SelectionData data(format_map_.GetFirstOf(requested_types));
231eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (data.IsValid()) {
232eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    std::string text = data.GetText();
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    *result = base::UTF8ToUTF16(text);
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return true;
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return false;
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
240eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool OSExchangeDataProviderAuraX11::GetURLAndTitle(
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    OSExchangeData::FilenameToURLPolicy policy,
242eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    GURL* url,
243eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    base::string16* title) const {
244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::vector< ::Atom> url_atoms = ui::GetURLAtomsFrom(&atom_cache_);
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::vector< ::Atom> requested_types;
246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ui::GetAtomIntersection(url_atoms, GetTargets(), &requested_types);
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
248eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ui::SelectionData data(format_map_.GetFirstOf(requested_types));
249eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (data.IsValid()) {
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // TODO(erg): Technically, both of these forms can accept multiple URLs,
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // but that doesn't match the assumptions of the rest of the system which
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // expect single types.
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
254eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (data.GetType() == atom_cache_.GetAtom(kMimeTypeMozillaURL)) {
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // Mozilla URLs are (UTF16: URL, newline, title).
256eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      base::string16 unparsed;
257eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      data.AssignTo(&unparsed);
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      std::vector<base::string16> tokens;
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      size_t num_tokens = Tokenize(unparsed, base::ASCIIToUTF16("\n"), &tokens);
2613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      if (num_tokens > 0) {
2623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        if (num_tokens > 1)
2633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          *title = tokens[1];
2643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        else
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          *title = base::string16();
2663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        *url = GURL(tokens[0]);
268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return true;
269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    } else if (data.GetType() == atom_cache_.GetAtom(
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   Clipboard::kMimeTypeURIList)) {
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      std::vector<std::string> tokens = ui::ParseURIList(data);
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      for (std::vector<std::string>::const_iterator it = tokens.begin();
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           it != tokens.end(); ++it) {
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        GURL test_url(*it);
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (!test_url.SchemeIsFile() ||
2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            policy == OSExchangeData::CONVERT_FILENAMES) {
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          *url = test_url;
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          *title = base::string16();
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          return true;
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return false;
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool OSExchangeDataProviderAuraX11::GetFilename(base::FilePath* path) const {
290effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  std::vector<FileInfo> filenames;
2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (GetFilenames(&filenames)) {
2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    *path = filenames.front().path;
2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return true;
2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return false;
297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool OSExchangeDataProviderAuraX11::GetFilenames(
300effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    std::vector<FileInfo>* filenames) const {
3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::vector< ::Atom> url_atoms = ui::GetURIListAtomsFrom(&atom_cache_);
3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::vector< ::Atom> requested_types;
3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ui::GetAtomIntersection(url_atoms, GetTargets(), &requested_types);
3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  filenames->clear();
3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ui::SelectionData data(format_map_.GetFirstOf(requested_types));
3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (data.IsValid()) {
3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::vector<std::string> tokens = ui::ParseURIList(data);
3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (std::vector<std::string>::const_iterator it = tokens.begin();
3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         it != tokens.end(); ++it) {
3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      GURL url(*it);
3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::FilePath file_path;
3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (url.SchemeIsFile() && net::FileURLToFilePath(url, &file_path)) {
314effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        filenames->push_back(FileInfo(file_path, base::FilePath()));
3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return !filenames->empty();
320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool OSExchangeDataProviderAuraX11::GetPickledData(
32390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const OSExchangeData::CustomFormat& format,
324eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    Pickle* pickle) const {
325eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::vector< ::Atom> requested_types;
326eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  requested_types.push_back(atom_cache_.GetAtom(format.ToString().c_str()));
327eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
328eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ui::SelectionData data(format_map_.GetFirstOf(requested_types));
329eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (data.IsValid()) {
330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Note that the pickle object on the right hand side of the assignment
331eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // only refers to the bytes in |data|. The assignment copies the data.
332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    *pickle = Pickle(reinterpret_cast<const char*>(data.GetData()),
333eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     static_cast<int>(data.GetSize()));
334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return true;
335eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
336eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return false;
338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool OSExchangeDataProviderAuraX11::HasString() const {
341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::vector< ::Atom> text_atoms = ui::GetTextAtomsFrom(&atom_cache_);
342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::vector< ::Atom> requested_types;
343eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ui::GetAtomIntersection(text_atoms, GetTargets(), &requested_types);
3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return !requested_types.empty() && !HasFile();
345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
347a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool OSExchangeDataProviderAuraX11::HasURL(
348a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    OSExchangeData::FilenameToURLPolicy policy) const {
349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::vector< ::Atom> url_atoms = ui::GetURLAtomsFrom(&atom_cache_);
350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::vector< ::Atom> requested_types;
351eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ui::GetAtomIntersection(url_atoms, GetTargets(), &requested_types);
3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (requested_types.empty())
3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The Linux desktop doesn't differentiate between files and URLs like
3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Windows does and stuffs all the data into one mime type.
3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ui::SelectionData data(format_map_.GetFirstOf(requested_types));
3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (data.IsValid()) {
3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (data.GetType() == atom_cache_.GetAtom(kMimeTypeMozillaURL)) {
3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // File managers shouldn't be using this type, so this is a URL.
3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return true;
3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else if (data.GetType() == atom_cache_.GetAtom(
3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ui::Clipboard::kMimeTypeURIList)) {
3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      std::vector<std::string> tokens = ui::ParseURIList(data);
3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      for (std::vector<std::string>::const_iterator it = tokens.begin();
3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           it != tokens.end(); ++it) {
368a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        if (!GURL(*it).SchemeIsFile() ||
369a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            policy == OSExchangeData::CONVERT_FILENAMES)
3705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          return true;
3715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return false;
3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return false;
378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool OSExchangeDataProviderAuraX11::HasFile() const {
3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::vector< ::Atom> url_atoms = ui::GetURIListAtomsFrom(&atom_cache_);
3825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::vector< ::Atom> requested_types;
3835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ui::GetAtomIntersection(url_atoms, GetTargets(), &requested_types);
3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (requested_types.empty())
3865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // To actually answer whether we have a file, we need to look through the
3895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // contents of the kMimeTypeURIList type, and see if any of them are file://
3905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // URIs.
3915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ui::SelectionData data(format_map_.GetFirstOf(requested_types));
3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (data.IsValid()) {
3935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::vector<std::string> tokens = ui::ParseURIList(data);
3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (std::vector<std::string>::const_iterator it = tokens.begin();
3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         it != tokens.end(); ++it) {
3965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      GURL url(*it);
3975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::FilePath file_path;
3985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (url.SchemeIsFile() && net::FileURLToFilePath(url, &file_path))
3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return true;
4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return false;
404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool OSExchangeDataProviderAuraX11::HasCustomFormat(
40790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const OSExchangeData::CustomFormat& format) const {
408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::vector< ::Atom> url_atoms;
409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  url_atoms.push_back(atom_cache_.GetAtom(format.ToString().c_str()));
410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::vector< ::Atom> requested_types;
411eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ui::GetAtomIntersection(url_atoms, GetTargets(), &requested_types);
412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return !requested_types.empty();
414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
416effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid OSExchangeDataProviderAuraX11::SetFileContents(
417effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const base::FilePath& filename,
418effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const std::string& file_contents) {
419effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK(!filename.empty());
420a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  DCHECK(format_map_.end() ==
421a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch         format_map_.find(atom_cache_.GetAtom(kMimeTypeMozillaURL)));
422effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
423effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  file_contents_name_ = filename;
424effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
425effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Direct save handling is a complicated juggling affair between this class,
426effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // SelectionFormat, and DesktopDragDropClientAuraX11. The general idea behind
427effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // the protocol is this:
428effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // - The source window sets its XdndDirectSave0 window property to the
429effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  //   proposed filename.
430effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // - When a target window receives the drop, it updates the XdndDirectSave0
431effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  //   property on the source window to the filename it would like the contents
432effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  //   to be saved to and then requests the XdndDirectSave0 type from the
433effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  //   source.
434effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // - The source is supposed to copy the file here and return success (S),
435effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  //   failure (F), or error (E).
436effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // - In this case, failure means the destination should try to populate the
437effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  //   file itself by copying the data from application/octet-stream. To make
438effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  //   things simpler for Chrome, we always 'fail' and let the destination do
439effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  //   the work.
440effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  std::string failure("F");
441effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  format_map_.Insert(
442effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      atom_cache_.GetAtom("XdndDirectSave0"),
443effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                          scoped_refptr<base::RefCountedMemory>(
444effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                              base::RefCountedString::TakeString(&failure)));
445effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  std::string file_contents_copy = file_contents;
446effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  format_map_.Insert(
447effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      atom_cache_.GetAtom("application/octet-stream"),
448effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      scoped_refptr<base::RefCountedMemory>(
449effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          base::RefCountedString::TakeString(&file_contents_copy)));
450effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
451effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
452eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid OSExchangeDataProviderAuraX11::SetHtml(const base::string16& html,
453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                            const GURL& base_url) {
454eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::vector<unsigned char> bytes;
455eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Manually jam a UTF16 BOM into bytes because otherwise, other programs will
456eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // assume UTF-8.
457eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bytes.push_back(0xFF);
458eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bytes.push_back(0xFE);
459eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ui::AddString16ToVector(html, &bytes);
460eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<base::RefCountedMemory> mem(
461eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      base::RefCountedBytes::TakeVector(&bytes));
462eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
463eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  format_map_.Insert(atom_cache_.GetAtom(Clipboard::kMimeTypeHTML), mem);
464c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
465c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
466eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool OSExchangeDataProviderAuraX11::GetHtml(base::string16* html,
467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                            GURL* base_url) const {
468c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::vector< ::Atom> url_atoms;
469c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  url_atoms.push_back(atom_cache_.GetAtom(Clipboard::kMimeTypeHTML));
470c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::vector< ::Atom> requested_types;
471eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ui::GetAtomIntersection(url_atoms, GetTargets(), &requested_types);
472c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
473eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ui::SelectionData data(format_map_.GetFirstOf(requested_types));
474eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (data.IsValid()) {
475eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    *html = data.GetHtml();
476c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    *base_url = GURL();
477c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return true;
478c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
480c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return false;
481c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
482c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
483c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool OSExchangeDataProviderAuraX11::HasHtml() const {
484c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::vector< ::Atom> url_atoms;
485c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  url_atoms.push_back(atom_cache_.GetAtom(Clipboard::kMimeTypeHTML));
486c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::vector< ::Atom> requested_types;
487eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ui::GetAtomIntersection(url_atoms, GetTargets(), &requested_types);
488c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
489c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return !requested_types.empty();
490c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
491c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
492c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void OSExchangeDataProviderAuraX11::SetDragImage(
493c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const gfx::ImageSkia& image,
494c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const gfx::Vector2d& cursor_offset) {
495eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  drag_image_ = image;
496eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  drag_image_offset_ = cursor_offset;
497c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
498c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
499c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const gfx::ImageSkia& OSExchangeDataProviderAuraX11::GetDragImage() const {
500c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return drag_image_;
501c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
502c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
503c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const gfx::Vector2d& OSExchangeDataProviderAuraX11::GetDragImageOffset() const {
504c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return drag_image_offset_;
505c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
506c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
507c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool OSExchangeDataProviderAuraX11::CanDispatchEvent(
508c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const PlatformEvent& event) {
509c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return event->xany.window == x_window_;
510c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
511c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
512c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochuint32_t OSExchangeDataProviderAuraX11::DispatchEvent(
513c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const PlatformEvent& event) {
514eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  XEvent* xev = event;
515eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  switch (xev->type) {
516eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case SelectionRequest:
517eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      selection_owner_.OnSelectionRequest(xev->xselectionrequest);
518c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      return ui::POST_DISPATCH_STOP_PROPAGATION;
519eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    default:
520eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      NOTIMPLEMENTED();
521eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
522c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return ui::POST_DISPATCH_NONE;
523c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
524c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
525c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool OSExchangeDataProviderAuraX11::GetPlainTextURL(GURL* url) const {
5265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::string16 text;
527eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetString(&text)) {
528eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    GURL test_url(text);
529eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (test_url.is_valid()) {
530eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      *url = test_url;
531eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      return true;
532eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
533eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
534eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
535c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return false;
536c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
537c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
538eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstd::vector< ::Atom> OSExchangeDataProviderAuraX11::GetTargets() const {
539eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return format_map_.GetTypes();
540eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
541eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
542c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)///////////////////////////////////////////////////////////////////////////////
543c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// OSExchangeData, public:
544c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
545c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static
546c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)OSExchangeData::Provider* OSExchangeData::CreateProvider() {
547c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return new OSExchangeDataProviderAuraX11();
548c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
549c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
550c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace ui
551