| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "content/browser/web_contents/web_drag_dest_gtk.h" | 5 #include "content/browser/web_contents/web_drag_dest_gtk.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 return modifier_state; | 46 return modifier_state; |
| 47 } | 47 } |
| 48 | 48 |
| 49 } // namespace | 49 } // namespace |
| 50 | 50 |
| 51 WebDragDestGtk::WebDragDestGtk(WebContents* web_contents, GtkWidget* widget) | 51 WebDragDestGtk::WebDragDestGtk(WebContents* web_contents, GtkWidget* widget) |
| 52 : web_contents_(web_contents), | 52 : web_contents_(web_contents), |
| 53 widget_(widget), | 53 widget_(widget), |
| 54 context_(NULL), | 54 context_(NULL), |
| 55 data_requests_(0), | 55 data_requests_(0), |
| 56 renderer_tainted_(false), |
| 56 delegate_(NULL), | 57 delegate_(NULL), |
| 57 canceled_(false), | 58 canceled_(false), |
| 58 method_factory_(this) { | 59 method_factory_(this) { |
| 59 gtk_drag_dest_set(widget, static_cast<GtkDestDefaults>(0), | 60 gtk_drag_dest_set(widget, static_cast<GtkDestDefaults>(0), |
| 60 NULL, 0, | 61 NULL, 0, |
| 61 static_cast<GdkDragAction>(GDK_ACTION_COPY | | 62 static_cast<GdkDragAction>(GDK_ACTION_COPY | |
| 62 GDK_ACTION_LINK | | 63 GDK_ACTION_LINK | |
| 63 GDK_ACTION_MOVE)); | 64 GDK_ACTION_MOVE)); |
| 64 | 65 |
| 65 // If adding a handler, make sure to update kNumGtkHandlers and add it to the | 66 // If adding a handler, make sure to update kNumGtkHandlers and add it to the |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 114 is_drop_target_ = false; | 115 is_drop_target_ = false; |
| 115 | 116 |
| 116 if (delegate()) | 117 if (delegate()) |
| 117 delegate()->DragInitialize(web_contents_); | 118 delegate()->DragInitialize(web_contents_); |
| 118 | 119 |
| 119 // text/plain must come before text/uri-list. This is a hack that works in | 120 // text/plain must come before text/uri-list. This is a hack that works in |
| 120 // conjunction with OnDragDataReceived. Since some file managers populate | 121 // conjunction with OnDragDataReceived. Since some file managers populate |
| 121 // text/plain with file URLs when dragging files, we want to handle | 122 // text/plain with file URLs when dragging files, we want to handle |
| 122 // text/uri-list after text/plain so that the plain text can be cleared if | 123 // text/uri-list after text/plain so that the plain text can be cleared if |
| 123 // it's a file drag. | 124 // it's a file drag. |
| 125 // Similarly, renderer taint must occur before anything else so we can |
| 126 // ignore potentially forged filenames when handling text/uri-list. |
| 124 static int supported_targets[] = { | 127 static int supported_targets[] = { |
| 128 ui::RENDERER_TAINT, |
| 125 ui::TEXT_PLAIN, | 129 ui::TEXT_PLAIN, |
| 126 ui::TEXT_URI_LIST, | 130 ui::TEXT_URI_LIST, |
| 127 ui::TEXT_HTML, | 131 ui::TEXT_HTML, |
| 128 ui::NETSCAPE_URL, | 132 ui::NETSCAPE_URL, |
| 129 ui::CHROME_NAMED_URL, | 133 ui::CHROME_NAMED_URL, |
| 130 // TODO(estade): support image drags? | 134 // TODO(estade): support image drags? |
| 131 ui::CUSTOM_DATA, | 135 ui::CUSTOM_DATA, |
| 132 }; | 136 }; |
| 133 | 137 |
| 138 renderer_tainted_ = false; |
| 134 // Add the delegate's requested target if applicable. Need to do this here | 139 // Add the delegate's requested target if applicable. Need to do this here |
| 135 // since gtk_drag_get_data will dispatch to our drag-data-received. | 140 // since gtk_drag_get_data will dispatch to our drag-data-received. |
| 136 data_requests_ = arraysize(supported_targets) + (delegate() ? 1 : 0); | 141 data_requests_ = arraysize(supported_targets) + (delegate() ? 1 : 0); |
| 137 for (size_t i = 0; i < arraysize(supported_targets); ++i) { | 142 for (size_t i = 0; i < arraysize(supported_targets); ++i) { |
| 138 gtk_drag_get_data(widget_, context, | 143 gtk_drag_get_data(widget_, context, |
| 139 ui::GetAtomForTarget(supported_targets[i]), | 144 ui::GetAtomForTarget(supported_targets[i]), |
| 140 time); | 145 time); |
| 141 } | 146 } |
| 142 | 147 |
| 143 if (delegate()) { | 148 if (delegate()) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 175 | 180 |
| 176 data_requests_--; | 181 data_requests_--; |
| 177 | 182 |
| 178 // Decode the data. | 183 // Decode the data. |
| 179 gint data_length = gtk_selection_data_get_length(data); | 184 gint data_length = gtk_selection_data_get_length(data); |
| 180 const guchar* raw_data = gtk_selection_data_get_data(data); | 185 const guchar* raw_data = gtk_selection_data_get_data(data); |
| 181 GdkAtom target = gtk_selection_data_get_target(data); | 186 GdkAtom target = gtk_selection_data_get_target(data); |
| 182 if (raw_data && data_length > 0) { | 187 if (raw_data && data_length > 0) { |
| 183 // If the source can't provide us with valid data for a requested target, | 188 // If the source can't provide us with valid data for a requested target, |
| 184 // raw_data will be NULL. | 189 // raw_data will be NULL. |
| 185 if (target == ui::GetAtomForTarget(ui::TEXT_PLAIN)) { | 190 if (target == ui::GetAtomForTarget(ui::RENDERER_TAINT)) { |
| 191 renderer_tainted_ = true; |
| 192 } else if (target == ui::GetAtomForTarget(ui::TEXT_PLAIN)) { |
| 186 guchar* text = gtk_selection_data_get_text(data); | 193 guchar* text = gtk_selection_data_get_text(data); |
| 187 if (text) { | 194 if (text) { |
| 188 drop_data_->text = base::NullableString16( | 195 drop_data_->text = base::NullableString16( |
| 189 base::UTF8ToUTF16(std::string(reinterpret_cast<const char*>(text))), | 196 base::UTF8ToUTF16(std::string(reinterpret_cast<const char*>(text))), |
| 190 false); | 197 false); |
| 191 g_free(text); | 198 g_free(text); |
| 192 } | 199 } |
| 193 } else if (target == ui::GetAtomForTarget(ui::TEXT_URI_LIST)) { | 200 } else if (target == ui::GetAtomForTarget(ui::TEXT_URI_LIST)) { |
| 194 gchar** uris = gtk_selection_data_get_uris(data); | 201 gchar** uris = gtk_selection_data_get_uris(data); |
| 195 if (uris) { | 202 if (uris) { |
| 196 drop_data_->url = GURL(); | 203 drop_data_->url = GURL(); |
| 197 for (gchar** uri_iter = uris; *uri_iter; uri_iter++) { | 204 for (gchar** uri_iter = uris; *uri_iter; uri_iter++) { |
| 198 // Most file managers populate text/uri-list with file URLs when | 205 // Most file managers populate text/uri-list with file URLs when |
| 199 // dragging files. To avoid exposing file system paths to web content, | 206 // dragging files. To avoid exposing file system paths to web content, |
| 200 // file URLs are never set as the URL content for the drop. | 207 // file URLs are never set as the URL content for the drop. |
| 201 // TODO(estade): Can the filenames have a non-UTF8 encoding? | 208 // TODO(estade): Can the filenames have a non-UTF8 encoding? |
| 202 GURL url(*uri_iter); | 209 GURL url(*uri_iter); |
| 203 base::FilePath file_path; | 210 base::FilePath file_path; |
| 204 if (url.SchemeIs(kFileScheme) && | 211 if (!renderer_tainted_ && |
| 212 url.SchemeIs(kFileScheme) && |
| 205 net::FileURLToFilePath(url, &file_path)) { | 213 net::FileURLToFilePath(url, &file_path)) { |
| 206 drop_data_->filenames.push_back( | 214 drop_data_->filenames.push_back(DropData::FileInfo( |
| 207 DropData::FileInfo(base::UTF8ToUTF16(file_path.value()), | 215 base::UTF8ToUTF16(file_path.value()), base::string16())); |
| 208 base::string16())); | |
| 209 // This is a hack. Some file managers also populate text/plain with | 216 // This is a hack. Some file managers also populate text/plain with |
| 210 // a file URL when dragging files, so we clear it to avoid exposing | 217 // a file URL when dragging files, so we clear it to avoid exposing |
| 211 // it to the web content. | 218 // it to the web content. |
| 212 drop_data_->text = base::NullableString16(); | 219 drop_data_->text = base::NullableString16(); |
| 213 } else if (!drop_data_->url.is_valid()) { | 220 } else if (!drop_data_->url.is_valid()) { |
| 214 // Also set the first non-file URL as the URL content for the drop. | 221 // Also set the first non-file URL as the URL content for the drop. |
| 215 drop_data_->url = url; | 222 drop_data_->url = url; |
| 216 } | 223 } |
| 217 } | 224 } |
| 218 g_strfreev(uris); | 225 g_strfreev(uris); |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 332 gtk_drag_finish(context, is_drop_target_, FALSE, time); | 339 gtk_drag_finish(context, is_drop_target_, FALSE, time); |
| 333 | 340 |
| 334 return TRUE; | 341 return TRUE; |
| 335 } | 342 } |
| 336 | 343 |
| 337 RenderViewHostImpl* WebDragDestGtk::GetRenderViewHost() const { | 344 RenderViewHostImpl* WebDragDestGtk::GetRenderViewHost() const { |
| 338 return static_cast<RenderViewHostImpl*>(web_contents_->GetRenderViewHost()); | 345 return static_cast<RenderViewHostImpl*>(web_contents_->GetRenderViewHost()); |
| 339 } | 346 } |
| 340 | 347 |
| 341 } // namespace content | 348 } // namespace content |
| OLD | NEW |