15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/web_contents/web_drag_source_gtk.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/nix/mime_util_xdg.h" 10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread_restrictions.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/download/drag_download_file.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/download/drag_download_util.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/render_view_host_delegate.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/render_view_host_impl.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/web_contents/drag_utils_gtk.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/web_contents/web_contents_impl.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/content_browser_client.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents_view.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/content_client.h" 21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "content/public/common/drop_data.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/file_stream.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/clipboard/custom_data_helper.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/dragdrop/gtk_dnd_util.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/gtk/gtk_screen_util.h" 2858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "ui/gfx/gtk_compat.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/gtk_util.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebDragOperation; 32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebDragOperationsMask; 33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebDragOperationNone; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebDragSourceGtk::WebDragSourceGtk(WebContents* web_contents) 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : web_contents_(static_cast<WebContentsImpl*>(web_contents)), 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_pixbuf_(NULL), 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_failed_(false), 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_widget_(gtk_invisible_new()), 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_context_(NULL), 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_icon_(gtk_window_new(GTK_WINDOW_POPUP)) { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signals_.Connect(drag_widget_, "drag-failed", 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) G_CALLBACK(OnDragFailedThunk), this); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signals_.Connect(drag_widget_, "drag-begin", 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) G_CALLBACK(OnDragBeginThunk), 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signals_.Connect(drag_widget_, "drag-end", 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) G_CALLBACK(OnDragEndThunk), this); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signals_.Connect(drag_widget_, "drag-data-get", 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) G_CALLBACK(OnDragDataGetThunk), this); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signals_.Connect(drag_icon_, "expose-event", 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) G_CALLBACK(OnDragIconExposeThunk), this); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebDragSourceGtk::~WebDragSourceGtk() { 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Break the current drag, if any. 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (drop_data_) { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_grab_add(drag_widget_); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_grab_remove(drag_widget_); 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoopForUI::current()->RemoveObserver(this); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drop_data_.reset(); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_widget_destroy(drag_widget_); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_widget_destroy(drag_icon_); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool WebDragSourceGtk::StartDragging(const DropData& drop_data, 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebDragOperationsMask allowed_ops, 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GdkEventButton* last_mouse_down, 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SkBitmap& image, 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Vector2d& image_offset) { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Guard against re-starting before previous drag completed. 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (drag_context_) { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int targets_mask = 0; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!drop_data.text.string().empty()) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) targets_mask |= ui::TEXT_PLAIN; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (drop_data.url.is_valid()) { 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) targets_mask |= ui::TEXT_URI_LIST; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) targets_mask |= ui::CHROME_NAMED_URL; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) targets_mask |= ui::NETSCAPE_URL; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!drop_data.html.string().empty()) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) targets_mask |= ui::TEXT_HTML; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!drop_data.file_contents.empty()) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) targets_mask |= ui::CHROME_WEBDROP_FILE_CONTENTS; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!drop_data.download_metadata.empty() && 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ParseDownloadMetadata(drop_data.download_metadata, 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &wide_download_mime_type_, 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &download_file_name_, 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &download_url_)) { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) targets_mask |= ui::DIRECT_SAVE_FILE; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!drop_data.custom_data.empty()) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) targets_mask |= ui::CUSTOM_DATA; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: Begin a drag even if no targets present. Otherwise, things like 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // draggable list elements will not work. 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch drop_data_.reset(new DropData(drop_data)); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The image we get from WebKit makes heavy use of alpha-shading. This looks 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bad on non-compositing WMs. Fall back to the default drag icon. 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!image.isNull() && ui::IsScreenComposited()) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_pixbuf_ = gfx::GdkPixbufFromSkBitmap(image); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_offset_ = image_offset; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkTargetList* list = ui::GetTargetListFromCodeMask(targets_mask); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (targets_mask & ui::CHROME_WEBDROP_FILE_CONTENTS) { 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Looking up the mime type can hit the disk. http://crbug.com/84896 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ThreadRestrictions::ScopedAllowIO allow_io; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_file_mime_type_ = gdk_atom_intern( 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::nix::GetDataMimeType(drop_data.file_contents).c_str(), FALSE); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_target_list_add(list, drag_file_mime_type_, 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, ui::CHROME_WEBDROP_FILE_CONTENTS); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_failed_ = false; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we don't pass an event, GDK won't know what event time to start grabbing 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // mouse events. Technically it's the mouse motion event and not the mouse 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // down event that causes the drag, but there's no reliable way to know 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // *which* motion event initiated the drag, so this will have to do. 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(estade): This can sometimes be very far off, e.g. if the user clicks 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and holds and doesn't start dragging for a long time. I doubt it matters 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // much, but we should probably look into the possibility of getting the 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // initiating event from webkit. 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_context_ = gtk_drag_begin(drag_widget_, list, 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebDragOpToGdkDragAction(allowed_ops), 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1, // Drags are always initiated by the left button. 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<GdkEvent*>(last_mouse_down)); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The drag adds a ref; let it own the list. 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_target_list_unref(list); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sometimes the drag fails to start; |context| will be NULL and we won't 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // get a drag-end signal. 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!drag_context_) { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_failed_ = true; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drop_data_.reset(); 147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoopForUI::current()->AddObserver(this); 151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return true; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebDragSourceGtk::WillProcessEvent(GdkEvent* event) { 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No-op. 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebDragSourceGtk::DidProcessEvent(GdkEvent* event) { 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (event->type != GDK_MOTION_NOTIFY) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GdkEventMotion* event_motion = reinterpret_cast<GdkEventMotion*>(event); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point client = ui::ClientPoint(GetContentNativeView()); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (web_contents_) { 166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) web_contents_->DragSourceMovedTo( 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client.x(), client.y(), 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(event_motion->x_root), 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(event_motion->y_root)); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebDragSourceGtk::OnDragDataGet(GtkWidget* sender, 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GdkDragContext* context, 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkSelectionData* selection_data, 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) guint target_type, 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) guint time) { 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kBitsPerByte = 8; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (target_type) { 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::TEXT_PLAIN: { 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string utf8_text = UTF16ToUTF8(drop_data_->text.string()); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_selection_data_set_text(selection_data, utf8_text.c_str(), 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) utf8_text.length()); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::TEXT_HTML: { 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(estade): change relative links to be absolute using 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |html_base_url|. 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string utf8_text = UTF16ToUTF8(drop_data_->html.string()); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_selection_data_set(selection_data, 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::GetAtomForTarget(ui::TEXT_HTML), 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kBitsPerByte, 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const guchar*>(utf8_text.c_str()), 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) utf8_text.length()); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::TEXT_URI_LIST: 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::CHROME_NAMED_URL: 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::NETSCAPE_URL: { 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::WriteURLWithName(selection_data, drop_data_->url, 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drop_data_->url_title, target_type); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::CHROME_WEBDROP_FILE_CONTENTS: { 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_selection_data_set( 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selection_data, 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_file_mime_type_, kBitsPerByte, 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const guchar*>(drop_data_->file_contents.data()), 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drop_data_->file_contents.length()); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::DIRECT_SAVE_FILE: { 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char status_code = 'E'; 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Retrieves the full file path (in file URL format) provided by the 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // drop target by reading from the source window's XdndDirectSave0 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // property. 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gint file_url_len = 0; 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) guchar* file_url_value = NULL; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (gdk_property_get(context->source_window, 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::GetAtomForTarget(ui::DIRECT_SAVE_FILE), 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::GetAtomForTarget(ui::TEXT_PLAIN_NO_CHARSET), 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1024, 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FALSE, 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &file_url_len, 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &file_url_value) && 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_url_value) { 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Convert from the file url to the file path. 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL file_url(std::string(reinterpret_cast<char*>(file_url_value), 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_url_len)); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_free(file_url_value); 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath file_path; 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (net::FileURLToFilePath(file_url, &file_path)) { 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Open the file as a stream. 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<net::FileStream> file_stream( 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateFileStreamForDrop( 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &file_path, 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetContentClient()->browser()->GetNetLog())); 247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (file_stream) { 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start downloading the file to the stream. 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<DragDownloadFile> drag_file_downloader = 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new DragDownloadFile( 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_path, 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_stream.Pass(), 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) download_url_, 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Referrer(web_contents_->GetURL(), 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drop_data_->referrer_policy), 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) web_contents_->GetEncoding(), 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) web_contents_); 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_file_downloader->Start( 259868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) new PromiseFileFinalizer(drag_file_downloader.get())); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set the status code to success. 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status_code = 'S'; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Return the status code to the file manager. 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_selection_data_set(selection_data, 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_selection_data_get_target(selection_data), 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kBitsPerByte, 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<guchar*>(&status_code), 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::CUSTOM_DATA: { 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pickle custom_data; 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::WriteCustomDataToPickle(drop_data_->custom_data, &custom_data); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_selection_data_set( 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selection_data, 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::GetAtomForTarget(ui::CUSTOM_DATA), 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kBitsPerByte, 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const guchar*>(custom_data.data()), 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) custom_data.size()); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gboolean WebDragSourceGtk::OnDragFailed(GtkWidget* sender, 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GdkDragContext* context, 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkDragResult result) { 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_failed_ = true; 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point root = ui::ScreenPoint(GetContentNativeView()); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point client = ui::ClientPoint(GetContentNativeView()); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (web_contents_) { 302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) web_contents_->DragSourceEndedAt( 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client.x(), client.y(), root.x(), root.y(), 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebDragOperationNone); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Let the native failure animation run. 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebDragSourceGtk::OnDragBegin(GtkWidget* sender, 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GdkDragContext* drag_context) { 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!download_url_.is_empty()) { 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Generate the file name based on both mime type and proposed file name. 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string default_name = 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetContentClient()->browser()->GetDefaultDownloadName(); 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath generated_download_file_name = 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::GenerateFileName(download_url_, 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string(), 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string(), 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) download_file_name_.value(), 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UTF16ToUTF8(wide_download_mime_type_), 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default_name); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Pass the file name to the drop target by setting the source window's 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // XdndDirectSave0 property. 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gdk_property_change(drag_context->source_window, 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::GetAtomForTarget(ui::DIRECT_SAVE_FILE), 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::GetAtomForTarget(ui::TEXT_PLAIN_NO_CHARSET), 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8, 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GDK_PROP_MODE_REPLACE, 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const guchar*>( 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) generated_download_file_name.value().c_str()), 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) generated_download_file_name.value().length()); 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (drag_pixbuf_) { 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_widget_set_size_request(drag_icon_, 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gdk_pixbuf_get_width(drag_pixbuf_), 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gdk_pixbuf_get_height(drag_pixbuf_)); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We only need to do this once. 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!gtk_widget_get_realized(drag_icon_)) { 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GdkScreen* screen = gtk_widget_get_screen(drag_icon_); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GdkColormap* rgba = gdk_screen_get_rgba_colormap(screen); 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rgba) 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_widget_set_colormap(drag_icon_, rgba); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_drag_set_icon_widget(drag_context, drag_icon_, 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_offset_.x(), image_offset_.y()); 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebDragSourceGtk::OnDragEnd(GtkWidget* sender, 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GdkDragContext* drag_context) { 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (drag_pixbuf_) { 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_object_unref(drag_pixbuf_); 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_pixbuf_ = NULL; 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoopForUI::current()->RemoveObserver(this); 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!download_url_.is_empty()) { 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gdk_property_delete(drag_context->source_window, 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::GetAtomForTarget(ui::DIRECT_SAVE_FILE)); 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!drag_failed_) { 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point root = ui::ScreenPoint(GetContentNativeView()); 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point client = ui::ClientPoint(GetContentNativeView()); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (web_contents_) { 374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) web_contents_->DragSourceEndedAt( 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client.x(), client.y(), root.x(), root.y(), 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GdkDragActionToWebDragOp(drag_context->action)); 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) web_contents_->SystemDragEnded(); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drop_data_.reset(); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_context_ = NULL; 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::NativeView WebDragSourceGtk::GetContentNativeView() const { 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return web_contents_->GetView()->GetContentNativeView(); 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gboolean WebDragSourceGtk::OnDragIconExpose(GtkWidget* sender, 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GdkEventExpose* event) { 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cairo_t* cr = gdk_cairo_create(event->window); 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gdk_cairo_rectangle(cr, &event->area); 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cairo_clip(cr); 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gdk_cairo_set_source_pixbuf(cr, drag_pixbuf_, 0, 0); 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cairo_paint(cr); 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cairo_destroy(cr); 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace content 404