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