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 |