OLD | NEW |
| (Empty) |
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 case ui::RENDERER_TAINT: | |
59 gtk_target_list_add(targets, | |
60 ui::GetAtomForTarget(ui::RENDERER_TAINT), 0, ui::RENDERER_TAINT); | |
61 break; | |
62 | |
63 default: | |
64 NOTREACHED() << " Unexpected target code: " << target_code; | |
65 } | |
66 } | |
67 | |
68 } // namespace | |
69 | |
70 GdkAtom GetAtomForTarget(int target) { | |
71 switch (target) { | |
72 case CHROME_TAB: | |
73 static const GdkAtom kTabAtom = gdk_atom_intern( | |
74 "application/x-chrome-tab", false); | |
75 return kTabAtom; | |
76 | |
77 case TEXT_HTML: | |
78 static const GdkAtom kHtmlAtom = gdk_atom_intern( | |
79 "text/html", false); | |
80 return kHtmlAtom; | |
81 | |
82 case CHROME_BOOKMARK_ITEM: | |
83 static const GdkAtom kBookmarkAtom = gdk_atom_intern( | |
84 "application/x-chrome-bookmark-item", false); | |
85 return kBookmarkAtom; | |
86 | |
87 case TEXT_PLAIN: | |
88 static const GdkAtom kTextAtom= gdk_atom_intern( | |
89 "text/plain;charset=utf-8", false); | |
90 return kTextAtom; | |
91 | |
92 case TEXT_URI_LIST: | |
93 static const GdkAtom kUrisAtom = gdk_atom_intern( | |
94 "text/uri-list", false); | |
95 return kUrisAtom; | |
96 | |
97 case CHROME_NAMED_URL: | |
98 static const GdkAtom kNamedUrl = gdk_atom_intern( | |
99 "application/x-chrome-named-url", false); | |
100 return kNamedUrl; | |
101 | |
102 case NETSCAPE_URL: | |
103 static const GdkAtom kNetscapeUrl = gdk_atom_intern( | |
104 "_NETSCAPE_URL", false); | |
105 return kNetscapeUrl; | |
106 | |
107 case TEXT_PLAIN_NO_CHARSET: | |
108 static const GdkAtom kTextNoCharsetAtom = gdk_atom_intern( | |
109 "text/plain", false); | |
110 return kTextNoCharsetAtom; | |
111 | |
112 case DIRECT_SAVE_FILE: | |
113 static const GdkAtom kXdsAtom = gdk_atom_intern( | |
114 "XdndDirectSave0", false); | |
115 return kXdsAtom; | |
116 | |
117 case CUSTOM_DATA: | |
118 static const GdkAtom kCustomData = gdk_atom_intern( | |
119 kMimeTypeWebCustomData, false); | |
120 return kCustomData; | |
121 | |
122 case RENDERER_TAINT: | |
123 static const GdkAtom kRendererTaint = gdk_atom_intern( | |
124 "chromium/x-renderer-taint", false); | |
125 return kRendererTaint; | |
126 | |
127 default: | |
128 NOTREACHED(); | |
129 } | |
130 | |
131 return NULL; | |
132 } | |
133 | |
134 GtkTargetList* GetTargetListFromCodeMask(int code_mask) { | |
135 GtkTargetList* targets = gtk_target_list_new(NULL, 0); | |
136 | |
137 for (size_t i = 1; i < INVALID_TARGET; i = i << 1) { | |
138 if (i == CHROME_WEBDROP_FILE_CONTENTS) | |
139 continue; | |
140 | |
141 if (i & code_mask) | |
142 AddTargetToList(targets, i); | |
143 } | |
144 | |
145 return targets; | |
146 } | |
147 | |
148 void SetSourceTargetListFromCodeMask(GtkWidget* source, int code_mask) { | |
149 GtkTargetList* targets = GetTargetListFromCodeMask(code_mask); | |
150 gtk_drag_source_set_target_list(source, targets); | |
151 gtk_target_list_unref(targets); | |
152 } | |
153 | |
154 void SetDestTargetList(GtkWidget* dest, const int* target_codes) { | |
155 GtkTargetList* targets = gtk_target_list_new(NULL, 0); | |
156 | |
157 for (size_t i = 0; target_codes[i] != -1; ++i) { | |
158 AddTargetToList(targets, target_codes[i]); | |
159 } | |
160 | |
161 gtk_drag_dest_set_target_list(dest, targets); | |
162 gtk_target_list_unref(targets); | |
163 } | |
164 | |
165 void WriteURLWithName(GtkSelectionData* selection_data, | |
166 const GURL& url, | |
167 base::string16 title, | |
168 int type) { | |
169 if (title.empty()) { | |
170 // We prefer to not have empty titles. Set it to the filename extracted | |
171 // from the URL. | |
172 title = base::UTF8ToUTF16(url.ExtractFileName()); | |
173 } | |
174 | |
175 switch (type) { | |
176 case TEXT_PLAIN: { | |
177 gtk_selection_data_set_text(selection_data, url.spec().c_str(), | |
178 url.spec().length()); | |
179 break; | |
180 } | |
181 case TEXT_URI_LIST: { | |
182 gchar* uri_array[2]; | |
183 uri_array[0] = strdup(url.spec().c_str()); | |
184 uri_array[1] = NULL; | |
185 gtk_selection_data_set_uris(selection_data, uri_array); | |
186 free(uri_array[0]); | |
187 break; | |
188 } | |
189 case CHROME_NAMED_URL: { | |
190 Pickle pickle; | |
191 pickle.WriteString(base::UTF16ToUTF8(title)); | |
192 pickle.WriteString(url.spec()); | |
193 gtk_selection_data_set( | |
194 selection_data, | |
195 GetAtomForTarget(ui::CHROME_NAMED_URL), | |
196 kBitsPerByte, | |
197 reinterpret_cast<const guchar*>(pickle.data()), | |
198 pickle.size()); | |
199 break; | |
200 } | |
201 case NETSCAPE_URL: { | |
202 // _NETSCAPE_URL format is URL + \n + title. | |
203 std::string utf8_text = url.spec() + "\n" + base::UTF16ToUTF8(title); | |
204 gtk_selection_data_set(selection_data, | |
205 gtk_selection_data_get_target(selection_data), | |
206 kBitsPerByte, | |
207 reinterpret_cast<const guchar*>(utf8_text.c_str()), | |
208 utf8_text.length()); | |
209 break; | |
210 } | |
211 | |
212 default: { | |
213 NOTREACHED(); | |
214 break; | |
215 } | |
216 } | |
217 } | |
218 | |
219 bool ExtractNamedURL(GtkSelectionData* selection_data, | |
220 GURL* url, | |
221 base::string16* title) { | |
222 if (!selection_data || gtk_selection_data_get_length(selection_data) <= 0) | |
223 return false; | |
224 | |
225 Pickle data( | |
226 reinterpret_cast<const char*>( | |
227 gtk_selection_data_get_data(selection_data)), | |
228 gtk_selection_data_get_length(selection_data)); | |
229 PickleIterator iter(data); | |
230 std::string title_utf8, url_utf8; | |
231 if (!data.ReadString(&iter, &title_utf8) || | |
232 !data.ReadString(&iter, &url_utf8)) { | |
233 return false; | |
234 } | |
235 | |
236 GURL gurl(url_utf8); | |
237 if (!gurl.is_valid()) | |
238 return false; | |
239 | |
240 *url = gurl; | |
241 *title = base::UTF8ToUTF16(title_utf8); | |
242 return true; | |
243 } | |
244 | |
245 bool ExtractURIList(GtkSelectionData* selection_data, std::vector<GURL>* urls) { | |
246 gchar** uris = gtk_selection_data_get_uris(selection_data); | |
247 if (!uris) | |
248 return false; | |
249 | |
250 for (size_t i = 0; uris[i] != NULL; ++i) { | |
251 GURL url(uris[i]); | |
252 if (url.is_valid()) | |
253 urls->push_back(url); | |
254 } | |
255 | |
256 g_strfreev(uris); | |
257 return true; | |
258 } | |
259 | |
260 bool ExtractNetscapeURL(GtkSelectionData* selection_data, | |
261 GURL* url, | |
262 base::string16* title) { | |
263 if (!selection_data || gtk_selection_data_get_length(selection_data) <= 0) | |
264 return false; | |
265 | |
266 // Find the first '\n' in the data. It is the separator between the url and | |
267 // the title. | |
268 std::string data( | |
269 reinterpret_cast<const char*>( | |
270 gtk_selection_data_get_data(selection_data)), | |
271 gtk_selection_data_get_length(selection_data)); | |
272 std::string::size_type newline = data.find('\n'); | |
273 if (newline == std::string::npos) | |
274 return false; | |
275 | |
276 GURL gurl(data.substr(0, newline)); | |
277 if (!gurl.is_valid()) | |
278 return false; | |
279 | |
280 *url = gurl; | |
281 *title = base::UTF8ToUTF16(data.substr(newline + 1)); | |
282 return true; | |
283 } | |
284 | |
285 } // namespace ui | |
OLD | NEW |