- add sources.
[platform/framework/web/crosswalk.git] / src / ui / base / dragdrop / gtk_dnd_util.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ui/base/dragdrop/gtk_dnd_util.h"
6
7 #include <string>
8
9 #include "base/logging.h"
10 #include "base/pickle.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "ui/base/clipboard/custom_data_helper.h"
13 #include "url/gurl.h"
14
15 namespace ui {
16
17 namespace {
18
19 const int kBitsPerByte = 8;
20
21 void AddTargetToList(GtkTargetList* targets, int target_code) {
22   switch (target_code) {
23     case ui::TEXT_PLAIN:
24       gtk_target_list_add_text_targets(targets, ui::TEXT_PLAIN);
25       break;
26
27     case ui::TEXT_URI_LIST:
28       gtk_target_list_add_uri_targets(targets, ui::TEXT_URI_LIST);
29       break;
30
31     case ui::TEXT_HTML:
32       gtk_target_list_add(
33           targets, ui::GetAtomForTarget(ui::TEXT_HTML), 0, ui::TEXT_HTML);
34       break;
35
36     case ui::NETSCAPE_URL:
37       gtk_target_list_add(targets,
38           ui::GetAtomForTarget(ui::NETSCAPE_URL), 0, ui::NETSCAPE_URL);
39       break;
40
41     case ui::CHROME_TAB:
42     case ui::CHROME_BOOKMARK_ITEM:
43     case ui::CHROME_NAMED_URL:
44       gtk_target_list_add(targets, ui::GetAtomForTarget(target_code),
45                           GTK_TARGET_SAME_APP, target_code);
46       break;
47
48     case ui::DIRECT_SAVE_FILE:
49       gtk_target_list_add(targets,
50           ui::GetAtomForTarget(ui::DIRECT_SAVE_FILE), 0, ui::DIRECT_SAVE_FILE);
51       break;
52
53     case ui::CUSTOM_DATA:
54       gtk_target_list_add(targets,
55           ui::GetAtomForTarget(ui::CUSTOM_DATA), 0, ui::CUSTOM_DATA);
56       break;
57
58     default:
59       NOTREACHED() << " Unexpected target code: " << target_code;
60   }
61 }
62
63 }  // namespace
64
65 GdkAtom GetAtomForTarget(int target) {
66   switch (target) {
67     case CHROME_TAB:
68       static const GdkAtom kTabAtom = gdk_atom_intern(
69           "application/x-chrome-tab", false);
70       return kTabAtom;
71
72     case TEXT_HTML:
73       static const GdkAtom kHtmlAtom = gdk_atom_intern(
74           "text/html", false);
75       return kHtmlAtom;
76
77     case CHROME_BOOKMARK_ITEM:
78       static const GdkAtom kBookmarkAtom = gdk_atom_intern(
79           "application/x-chrome-bookmark-item", false);
80       return kBookmarkAtom;
81
82     case TEXT_PLAIN:
83       static const GdkAtom kTextAtom= gdk_atom_intern(
84           "text/plain;charset=utf-8", false);
85       return kTextAtom;
86
87     case TEXT_URI_LIST:
88       static const GdkAtom kUrisAtom = gdk_atom_intern(
89           "text/uri-list", false);
90       return kUrisAtom;
91
92     case CHROME_NAMED_URL:
93       static const GdkAtom kNamedUrl = gdk_atom_intern(
94           "application/x-chrome-named-url", false);
95       return kNamedUrl;
96
97     case NETSCAPE_URL:
98       static const GdkAtom kNetscapeUrl = gdk_atom_intern(
99           "_NETSCAPE_URL", false);
100       return kNetscapeUrl;
101
102     case TEXT_PLAIN_NO_CHARSET:
103       static const GdkAtom kTextNoCharsetAtom = gdk_atom_intern(
104           "text/plain", false);
105       return kTextNoCharsetAtom;
106
107     case DIRECT_SAVE_FILE:
108       static const GdkAtom kXdsAtom = gdk_atom_intern(
109           "XdndDirectSave0", false);
110       return kXdsAtom;
111
112     case CUSTOM_DATA:
113       static const GdkAtom kCustomData = gdk_atom_intern(
114           kMimeTypeWebCustomData, false);
115       return kCustomData;
116
117     default:
118       NOTREACHED();
119   }
120
121   return NULL;
122 }
123
124 GtkTargetList* GetTargetListFromCodeMask(int code_mask) {
125   GtkTargetList* targets = gtk_target_list_new(NULL, 0);
126
127   for (size_t i = 1; i < INVALID_TARGET; i = i << 1) {
128     if (i == CHROME_WEBDROP_FILE_CONTENTS)
129       continue;
130
131     if (i & code_mask)
132       AddTargetToList(targets, i);
133   }
134
135   return targets;
136 }
137
138 void SetSourceTargetListFromCodeMask(GtkWidget* source, int code_mask) {
139   GtkTargetList* targets = GetTargetListFromCodeMask(code_mask);
140   gtk_drag_source_set_target_list(source, targets);
141   gtk_target_list_unref(targets);
142 }
143
144 void SetDestTargetList(GtkWidget* dest, const int* target_codes) {
145   GtkTargetList* targets = gtk_target_list_new(NULL, 0);
146
147   for (size_t i = 0; target_codes[i] != -1; ++i) {
148     AddTargetToList(targets, target_codes[i]);
149   }
150
151   gtk_drag_dest_set_target_list(dest, targets);
152   gtk_target_list_unref(targets);
153 }
154
155 void WriteURLWithName(GtkSelectionData* selection_data,
156                       const GURL& url,
157                       base::string16 title,
158                       int type) {
159   if (title.empty()) {
160     // We prefer to not have empty titles. Set it to the filename extracted
161     // from the URL.
162     title = UTF8ToUTF16(url.ExtractFileName());
163   }
164
165   switch (type) {
166     case TEXT_PLAIN: {
167       gtk_selection_data_set_text(selection_data, url.spec().c_str(),
168                                   url.spec().length());
169       break;
170     }
171     case TEXT_URI_LIST: {
172       gchar* uri_array[2];
173       uri_array[0] = strdup(url.spec().c_str());
174       uri_array[1] = NULL;
175       gtk_selection_data_set_uris(selection_data, uri_array);
176       free(uri_array[0]);
177       break;
178     }
179     case CHROME_NAMED_URL: {
180       Pickle pickle;
181       pickle.WriteString(UTF16ToUTF8(title));
182       pickle.WriteString(url.spec());
183       gtk_selection_data_set(
184           selection_data,
185           GetAtomForTarget(ui::CHROME_NAMED_URL),
186           kBitsPerByte,
187           reinterpret_cast<const guchar*>(pickle.data()),
188           pickle.size());
189       break;
190     }
191     case NETSCAPE_URL: {
192       // _NETSCAPE_URL format is URL + \n + title.
193       std::string utf8_text = url.spec() + "\n" + UTF16ToUTF8(title);
194       gtk_selection_data_set(selection_data,
195                              gtk_selection_data_get_target(selection_data),
196                              kBitsPerByte,
197                              reinterpret_cast<const guchar*>(utf8_text.c_str()),
198                              utf8_text.length());
199       break;
200     }
201
202     default: {
203       NOTREACHED();
204       break;
205     }
206   }
207 }
208
209 bool ExtractNamedURL(GtkSelectionData* selection_data,
210                      GURL* url,
211                      base::string16* title) {
212   if (!selection_data || gtk_selection_data_get_length(selection_data) <= 0)
213     return false;
214
215   Pickle data(
216       reinterpret_cast<const char*>(
217           gtk_selection_data_get_data(selection_data)),
218       gtk_selection_data_get_length(selection_data));
219   PickleIterator iter(data);
220   std::string title_utf8, url_utf8;
221   if (!data.ReadString(&iter, &title_utf8) ||
222       !data.ReadString(&iter, &url_utf8)) {
223     return false;
224   }
225
226   GURL gurl(url_utf8);
227   if (!gurl.is_valid())
228     return false;
229
230   *url = gurl;
231   *title = UTF8ToUTF16(title_utf8);
232   return true;
233 }
234
235 bool ExtractURIList(GtkSelectionData* selection_data, std::vector<GURL>* urls) {
236   gchar** uris = gtk_selection_data_get_uris(selection_data);
237   if (!uris)
238     return false;
239
240   for (size_t i = 0; uris[i] != NULL; ++i) {
241     GURL url(uris[i]);
242     if (url.is_valid())
243       urls->push_back(url);
244   }
245
246   g_strfreev(uris);
247   return true;
248 }
249
250 bool ExtractNetscapeURL(GtkSelectionData* selection_data,
251                         GURL* url,
252                         base::string16* title) {
253   if (!selection_data || gtk_selection_data_get_length(selection_data) <= 0)
254     return false;
255
256   // Find the first '\n' in the data. It is the separator between the url and
257   // the title.
258   std::string data(
259       reinterpret_cast<const char*>(
260           gtk_selection_data_get_data(selection_data)),
261       gtk_selection_data_get_length(selection_data));
262   std::string::size_type newline = data.find('\n');
263   if (newline == std::string::npos)
264     return false;
265
266   GURL gurl(data.substr(0, newline));
267   if (!gurl.is_valid())
268     return false;
269
270   *url = gurl;
271   *title = UTF8ToUTF16(data.substr(newline + 1));
272   return true;
273 }
274
275 }  // namespace ui