| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/tab_contents/web_drag_dest_gtk.h" | 5 #include "chrome/browser/tab_contents/web_drag_dest_gtk.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "app/gtk_dnd_util.h" | |
| 10 #include "base/file_path.h" | 9 #include "base/file_path.h" |
| 11 #include "base/utf_string_conversions.h" | 10 #include "base/utf_string_conversions.h" |
| 12 #include "chrome/browser/bookmarks/bookmark_node_data.h" | 11 #include "chrome/browser/bookmarks/bookmark_node_data.h" |
| 13 #include "chrome/browser/gtk/bookmark_utils_gtk.h" | 12 #include "chrome/browser/gtk/bookmark_utils_gtk.h" |
| 14 #include "chrome/browser/gtk/gtk_util.h" | 13 #include "chrome/browser/gtk/gtk_util.h" |
| 15 #include "chrome/browser/renderer_host/render_view_host.h" | 14 #include "chrome/browser/renderer_host/render_view_host.h" |
| 16 #include "chrome/browser/tab_contents/tab_contents.h" | 15 #include "chrome/browser/tab_contents/tab_contents.h" |
| 17 #include "chrome/common/url_constants.h" | 16 #include "chrome/common/url_constants.h" |
| 18 #include "net/base/net_util.h" | 17 #include "net/base/net_util.h" |
| 18 #include "ui/base/dragdrop/gtk_dnd_util.h" |
| 19 | 19 |
| 20 using WebKit::WebDragOperation; | 20 using WebKit::WebDragOperation; |
| 21 using WebKit::WebDragOperationNone; | 21 using WebKit::WebDragOperationNone; |
| 22 | 22 |
| 23 namespace { | 23 namespace { |
| 24 | 24 |
| 25 // Returns the bookmark target atom, based on the underlying toolkit. | 25 // Returns the bookmark target atom, based on the underlying toolkit. |
| 26 // | 26 // |
| 27 // For GTK, bookmark drag data is encoded as pickle and associated with | 27 // For GTK, bookmark drag data is encoded as pickle and associated with |
| 28 // gtk_dnd_util::CHROME_BOOKMARK_ITEM. See | 28 // ui::CHROME_BOOKMARK_ITEM. See // bookmark_utils::WriteBookmarksToSelection() |
| 29 // bookmark_utils::WriteBookmarksToSelection() for details. | 29 // for details. |
| 30 // For Views, bookmark drag data is encoded in the same format, and | 30 // For Views, bookmark drag data is encoded in the same format, and |
| 31 // associated with a custom format. See BookmarkNodeData::Write() for | 31 // associated with a custom format. See BookmarkNodeData::Write() for |
| 32 // details. | 32 // details. |
| 33 GdkAtom GetBookmarkTargetAtom() { | 33 GdkAtom GetBookmarkTargetAtom() { |
| 34 #if defined(TOOLKIT_VIEWS) | 34 #if defined(TOOLKIT_VIEWS) |
| 35 return BookmarkNodeData::GetBookmarkCustomFormat(); | 35 return BookmarkNodeData::GetBookmarkCustomFormat(); |
| 36 #else | 36 #else |
| 37 return gtk_dnd_util::GetAtomForTarget(gtk_dnd_util::CHROME_BOOKMARK_ITEM); | 37 return ui::GetAtomForTarget(ui::CHROME_BOOKMARK_ITEM); |
| 38 #endif | 38 #endif |
| 39 } | 39 } |
| 40 | 40 |
| 41 } // namespace | 41 } // namespace |
| 42 | 42 |
| 43 WebDragDestGtk::WebDragDestGtk(TabContents* tab_contents, GtkWidget* widget) | 43 WebDragDestGtk::WebDragDestGtk(TabContents* tab_contents, GtkWidget* widget) |
| 44 : tab_contents_(tab_contents), | 44 : tab_contents_(tab_contents), |
| 45 widget_(widget), | 45 widget_(widget), |
| 46 context_(NULL), | 46 context_(NULL), |
| 47 method_factory_(this) { | 47 method_factory_(this) { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 97 drop_data_.reset(new WebDropData); | 97 drop_data_.reset(new WebDropData); |
| 98 bookmark_drag_data_.Clear(); | 98 bookmark_drag_data_.Clear(); |
| 99 is_drop_target_ = false; | 99 is_drop_target_ = false; |
| 100 | 100 |
| 101 // text/plain must come before text/uri-list. This is a hack that works in | 101 // text/plain must come before text/uri-list. This is a hack that works in |
| 102 // conjunction with OnDragDataReceived. Since some file managers populate | 102 // conjunction with OnDragDataReceived. Since some file managers populate |
| 103 // text/plain with file URLs when dragging files, we want to handle | 103 // text/plain with file URLs when dragging files, we want to handle |
| 104 // text/uri-list after text/plain so that the plain text can be cleared if | 104 // text/uri-list after text/plain so that the plain text can be cleared if |
| 105 // it's a file drag. | 105 // it's a file drag. |
| 106 static int supported_targets[] = { | 106 static int supported_targets[] = { |
| 107 gtk_dnd_util::TEXT_PLAIN, | 107 ui::TEXT_PLAIN, |
| 108 gtk_dnd_util::TEXT_URI_LIST, | 108 ui::TEXT_URI_LIST, |
| 109 gtk_dnd_util::TEXT_HTML, | 109 ui::TEXT_HTML, |
| 110 gtk_dnd_util::NETSCAPE_URL, | 110 ui::NETSCAPE_URL, |
| 111 gtk_dnd_util::CHROME_NAMED_URL, | 111 ui::CHROME_NAMED_URL, |
| 112 // TODO(estade): support image drags? | 112 // TODO(estade): support image drags? |
| 113 }; | 113 }; |
| 114 | 114 |
| 115 // Add the bookmark target as well. | 115 // Add the bookmark target as well. |
| 116 data_requests_ = arraysize(supported_targets) + 1; | 116 data_requests_ = arraysize(supported_targets) + 1; |
| 117 for (size_t i = 0; i < arraysize(supported_targets); ++i) { | 117 for (size_t i = 0; i < arraysize(supported_targets); ++i) { |
| 118 gtk_drag_get_data(widget_, context, | 118 gtk_drag_get_data(widget_, context, |
| 119 gtk_dnd_util::GetAtomForTarget(supported_targets[i]), | 119 ui::GetAtomForTarget(supported_targets[i]), |
| 120 time); | 120 time); |
| 121 } | 121 } |
| 122 | 122 |
| 123 gtk_drag_get_data(widget_, context, GetBookmarkTargetAtom(), time); | 123 gtk_drag_get_data(widget_, context, GetBookmarkTargetAtom(), time); |
| 124 } else if (data_requests_ == 0) { | 124 } else if (data_requests_ == 0) { |
| 125 tab_contents_->render_view_host()-> | 125 tab_contents_->render_view_host()-> |
| 126 DragTargetDragOver( | 126 DragTargetDragOver( |
| 127 gtk_util::ClientPoint(widget_), | 127 gtk_util::ClientPoint(widget_), |
| 128 gtk_util::ScreenPoint(widget_), | 128 gtk_util::ScreenPoint(widget_), |
| 129 gtk_util::GdkDragActionToWebDragOp(context->actions)); | 129 gtk_util::GdkDragActionToWebDragOp(context->actions)); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 144 // care about. | 144 // care about. |
| 145 if (context != context_) | 145 if (context != context_) |
| 146 return; | 146 return; |
| 147 | 147 |
| 148 data_requests_--; | 148 data_requests_--; |
| 149 | 149 |
| 150 // Decode the data. | 150 // Decode the data. |
| 151 if (data->data && data->length > 0) { | 151 if (data->data && data->length > 0) { |
| 152 // If the source can't provide us with valid data for a requested target, | 152 // If the source can't provide us with valid data for a requested target, |
| 153 // data->data will be NULL. | 153 // data->data will be NULL. |
| 154 if (data->target == | 154 if (data->target == ui::GetAtomForTarget(ui::TEXT_PLAIN)) { |
| 155 gtk_dnd_util::GetAtomForTarget(gtk_dnd_util::TEXT_PLAIN)) { | |
| 156 guchar* text = gtk_selection_data_get_text(data); | 155 guchar* text = gtk_selection_data_get_text(data); |
| 157 if (text) { | 156 if (text) { |
| 158 drop_data_->plain_text = | 157 drop_data_->plain_text = |
| 159 UTF8ToUTF16(std::string(reinterpret_cast<char*>(text), | 158 UTF8ToUTF16(std::string(reinterpret_cast<char*>(text), |
| 160 data->length)); | 159 data->length)); |
| 161 g_free(text); | 160 g_free(text); |
| 162 } | 161 } |
| 163 } else if (data->target == | 162 } else if (data->target == ui::GetAtomForTarget(ui::TEXT_URI_LIST)) { |
| 164 gtk_dnd_util::GetAtomForTarget(gtk_dnd_util::TEXT_URI_LIST)) { | |
| 165 gchar** uris = gtk_selection_data_get_uris(data); | 163 gchar** uris = gtk_selection_data_get_uris(data); |
| 166 if (uris) { | 164 if (uris) { |
| 167 drop_data_->url = GURL(); | 165 drop_data_->url = GURL(); |
| 168 for (gchar** uri_iter = uris; *uri_iter; uri_iter++) { | 166 for (gchar** uri_iter = uris; *uri_iter; uri_iter++) { |
| 169 // Most file managers populate text/uri-list with file URLs when | 167 // Most file managers populate text/uri-list with file URLs when |
| 170 // dragging files. To avoid exposing file system paths to web content, | 168 // dragging files. To avoid exposing file system paths to web content, |
| 171 // file URLs are never set as the URL content for the drop. | 169 // file URLs are never set as the URL content for the drop. |
| 172 // TODO(estade): Can the filenames have a non-UTF8 encoding? | 170 // TODO(estade): Can the filenames have a non-UTF8 encoding? |
| 173 GURL url(*uri_iter); | 171 GURL url(*uri_iter); |
| 174 FilePath file_path; | 172 FilePath file_path; |
| 175 if (url.SchemeIs(chrome::kFileScheme) && | 173 if (url.SchemeIs(chrome::kFileScheme) && |
| 176 net::FileURLToFilePath(url, &file_path)) { | 174 net::FileURLToFilePath(url, &file_path)) { |
| 177 drop_data_->filenames.push_back(UTF8ToUTF16(file_path.value())); | 175 drop_data_->filenames.push_back(UTF8ToUTF16(file_path.value())); |
| 178 // This is a hack. Some file managers also populate text/plain with | 176 // This is a hack. Some file managers also populate text/plain with |
| 179 // a file URL when dragging files, so we clear it to avoid exposing | 177 // a file URL when dragging files, so we clear it to avoid exposing |
| 180 // it to the web content. | 178 // it to the web content. |
| 181 drop_data_->plain_text.clear(); | 179 drop_data_->plain_text.clear(); |
| 182 } else if (!drop_data_->url.is_valid()) { | 180 } else if (!drop_data_->url.is_valid()) { |
| 183 // Also set the first non-file URL as the URL content for the drop. | 181 // Also set the first non-file URL as the URL content for the drop. |
| 184 drop_data_->url = url; | 182 drop_data_->url = url; |
| 185 } | 183 } |
| 186 } | 184 } |
| 187 g_strfreev(uris); | 185 g_strfreev(uris); |
| 188 } | 186 } |
| 189 } else if (data->target == | 187 } else if (data->target == ui::GetAtomForTarget(ui::TEXT_HTML)) { |
| 190 gtk_dnd_util::GetAtomForTarget(gtk_dnd_util::TEXT_HTML)) { | |
| 191 // TODO(estade): Can the html have a non-UTF8 encoding? | 188 // TODO(estade): Can the html have a non-UTF8 encoding? |
| 192 drop_data_->text_html = | 189 drop_data_->text_html = |
| 193 UTF8ToUTF16(std::string(reinterpret_cast<char*>(data->data), | 190 UTF8ToUTF16(std::string(reinterpret_cast<char*>(data->data), |
| 194 data->length)); | 191 data->length)); |
| 195 // We leave the base URL empty. | 192 // We leave the base URL empty. |
| 196 } else if (data->target == | 193 } else if (data->target == ui::GetAtomForTarget(ui::NETSCAPE_URL)) { |
| 197 gtk_dnd_util::GetAtomForTarget(gtk_dnd_util::NETSCAPE_URL)) { | |
| 198 std::string netscape_url(reinterpret_cast<char*>(data->data), | 194 std::string netscape_url(reinterpret_cast<char*>(data->data), |
| 199 data->length); | 195 data->length); |
| 200 size_t split = netscape_url.find_first_of('\n'); | 196 size_t split = netscape_url.find_first_of('\n'); |
| 201 if (split != std::string::npos) { | 197 if (split != std::string::npos) { |
| 202 drop_data_->url = GURL(netscape_url.substr(0, split)); | 198 drop_data_->url = GURL(netscape_url.substr(0, split)); |
| 203 if (split < netscape_url.size() - 1) | 199 if (split < netscape_url.size() - 1) |
| 204 drop_data_->url_title = UTF8ToUTF16(netscape_url.substr(split + 1)); | 200 drop_data_->url_title = UTF8ToUTF16(netscape_url.substr(split + 1)); |
| 205 } | 201 } |
| 206 } else if (data->target == | 202 } else if (data->target == ui::GetAtomForTarget(ui::CHROME_NAMED_URL)) { |
| 207 gtk_dnd_util::GetAtomForTarget(gtk_dnd_util::CHROME_NAMED_URL)) { | 203 ui::ExtractNamedURL(data, &drop_data_->url, &drop_data_->url_title); |
| 208 gtk_dnd_util::ExtractNamedURL(data, | |
| 209 &drop_data_->url, &drop_data_->url_title); | |
| 210 } | 204 } |
| 211 } | 205 } |
| 212 | 206 |
| 213 // For CHROME_BOOKMARK_ITEM, we have to handle the case where the drag source | 207 // For CHROME_BOOKMARK_ITEM, we have to handle the case where the drag source |
| 214 // doesn't have any data available for us. In this case we try to synthesize a | 208 // doesn't have any data available for us. In this case we try to synthesize a |
| 215 // URL bookmark. | 209 // URL bookmark. |
| 216 // Note that bookmark drag data is encoded in the same format for both | 210 // Note that bookmark drag data is encoded in the same format for both |
| 217 // GTK and Views, hence we can share the same logic here. | 211 // GTK and Views, hence we can share the same logic here. |
| 218 if (data->target == GetBookmarkTargetAtom()) { | 212 if (data->target == GetBookmarkTargetAtom()) { |
| 219 if (data->data && data->length > 0) { | 213 if (data->data && data->length > 0) { |
| 220 bookmark_drag_data_.ReadFromVector( | 214 bookmark_drag_data_.ReadFromVector( |
| 221 bookmark_utils::GetNodesFromSelection( | 215 bookmark_utils::GetNodesFromSelection( |
| 222 NULL, data, | 216 NULL, data, |
| 223 gtk_dnd_util::CHROME_BOOKMARK_ITEM, | 217 ui::CHROME_BOOKMARK_ITEM, |
| 224 tab_contents_->profile(), NULL, NULL)); | 218 tab_contents_->profile(), NULL, NULL)); |
| 225 bookmark_drag_data_.SetOriginatingProfile(tab_contents_->profile()); | 219 bookmark_drag_data_.SetOriginatingProfile(tab_contents_->profile()); |
| 226 } else { | 220 } else { |
| 227 bookmark_drag_data_.ReadFromTuple(drop_data_->url, | 221 bookmark_drag_data_.ReadFromTuple(drop_data_->url, |
| 228 drop_data_->url_title); | 222 drop_data_->url_title); |
| 229 } | 223 } |
| 230 } | 224 } |
| 231 | 225 |
| 232 if (data_requests_ == 0) { | 226 if (data_requests_ == 0) { |
| 233 // Tell the renderer about the drag. | 227 // Tell the renderer about the drag. |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 278 // support for (at the moment experimental) drag and drop extensions. | 272 // support for (at the moment experimental) drag and drop extensions. |
| 279 if (tab_contents_->GetBookmarkDragDelegate()) | 273 if (tab_contents_->GetBookmarkDragDelegate()) |
| 280 tab_contents_->GetBookmarkDragDelegate()->OnDrop(bookmark_drag_data_); | 274 tab_contents_->GetBookmarkDragDelegate()->OnDrop(bookmark_drag_data_); |
| 281 | 275 |
| 282 // The second parameter is just an educated guess as to whether or not the | 276 // The second parameter is just an educated guess as to whether or not the |
| 283 // drag succeeded, but at least we will get the drag-end animation right | 277 // drag succeeded, but at least we will get the drag-end animation right |
| 284 // sometimes. | 278 // sometimes. |
| 285 gtk_drag_finish(context, is_drop_target_, FALSE, time); | 279 gtk_drag_finish(context, is_drop_target_, FALSE, time); |
| 286 return TRUE; | 280 return TRUE; |
| 287 } | 281 } |
| OLD | NEW |