| 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 |