172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/tab_contents/web_drag_dest_gtk.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string> 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/file_path.h" 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/utf_string_conversions.h" 11201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "chrome/browser/bookmarks/bookmark_node_data.h" 12dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/ui/gtk/bookmarks/bookmark_utils_gtk.h" 1372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/gtk_util.h" 14513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/common/url_constants.h" 15dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/render_view_host.h" 16dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h" 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_util.h" 1872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/dragdrop/gtk_dnd_util.h" 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing WebKit::WebDragOperation; 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing WebKit::WebDragOperationNone; 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 23731df977c0511bca2206b5f333555b1205ff1f43Iain Merricknamespace { 24731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 25731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Returns the bookmark target atom, based on the underlying toolkit. 26731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// 27731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// For GTK, bookmark drag data is encoded as pickle and associated with 2872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// ui::CHROME_BOOKMARK_ITEM. See // bookmark_utils::WriteBookmarksToSelection() 2972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// for details. 30731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// For Views, bookmark drag data is encoded in the same format, and 31201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// associated with a custom format. See BookmarkNodeData::Write() for 32731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// details. 33731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickGdkAtom GetBookmarkTargetAtom() { 34731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#if defined(TOOLKIT_VIEWS) 35201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch return BookmarkNodeData::GetBookmarkCustomFormat(); 36731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#else 3772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return ui::GetAtomForTarget(ui::CHROME_BOOKMARK_ITEM); 38731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#endif 39731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 40731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 41731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} // namespace 42731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochWebDragDestGtk::WebDragDestGtk(TabContents* tab_contents, GtkWidget* widget) 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : tab_contents_(tab_contents), 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch widget_(widget), 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch context_(NULL), 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch method_factory_(this) { 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_drag_dest_set(widget, static_cast<GtkDestDefaults>(0), 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NULL, 0, 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<GdkDragAction>(GDK_ACTION_COPY | 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GDK_ACTION_LINK | 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GDK_ACTION_MOVE)); 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_signal_connect(widget, "drag-motion", 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch G_CALLBACK(OnDragMotionThunk), this); 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_signal_connect(widget, "drag-leave", 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch G_CALLBACK(OnDragLeaveThunk), this); 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_signal_connect(widget, "drag-drop", 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch G_CALLBACK(OnDragDropThunk), this); 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_signal_connect(widget, "drag-data-received", 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch G_CALLBACK(OnDragDataReceivedThunk), this); 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(tony): Need a drag-data-delete handler for moving content out of 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the tab contents. http://crbug.com/38989 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch destroy_handler_ = g_signal_connect( 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch widget, "destroy", G_CALLBACK(gtk_widget_destroyed), &widget_); 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochWebDragDestGtk::~WebDragDestGtk() { 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (widget_) { 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_drag_dest_unset(widget_); 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_signal_handler_disconnect(widget_, destroy_handler_); 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebDragDestGtk::UpdateDragStatus(WebDragOperation operation) { 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (context_) { 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch is_drop_target_ = operation != WebDragOperationNone; 78731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick gdk_drag_status(context_, gtk_util::WebDragOpToGdkDragAction(operation), 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drag_over_time_); 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebDragDestGtk::DragLeave() { 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_contents_->render_view_host()->DragTargetDragLeave(); 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tab_contents_->GetBookmarkDragDelegate()) { 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_contents_->GetBookmarkDragDelegate()->OnDragLeave(bookmark_drag_data_); 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean WebDragDestGtk::OnDragMotion(GtkWidget* sender, 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GdkDragContext* context, 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gint x, gint y, 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint time) { 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (context_ != context) { 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch context_ = context; 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drop_data_.reset(new WebDropData); 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bookmark_drag_data_.Clear(); 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch is_drop_target_ = false; 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // text/plain must come before text/uri-list. This is a hack that works in 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // conjunction with OnDragDataReceived. Since some file managers populate 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // text/plain with file URLs when dragging files, we want to handle 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // text/uri-list after text/plain so that the plain text can be cleared if 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // it's a file drag. 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static int supported_targets[] = { 10772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ui::TEXT_PLAIN, 10872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ui::TEXT_URI_LIST, 10972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ui::TEXT_HTML, 11072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ui::NETSCAPE_URL, 11172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ui::CHROME_NAMED_URL, 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(estade): support image drags? 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 115731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Add the bookmark target as well. 116731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick data_requests_ = arraysize(supported_targets) + 1; 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < arraysize(supported_targets); ++i) { 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_drag_get_data(widget_, context, 11972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ui::GetAtomForTarget(supported_targets[i]), 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch time); 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 122731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 123731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick gtk_drag_get_data(widget_, context, GetBookmarkTargetAtom(), time); 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (data_requests_ == 0) { 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_contents_->render_view_host()-> 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DragTargetDragOver( 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_util::ClientPoint(widget_), 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_util::ScreenPoint(widget_), 129731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick gtk_util::GdkDragActionToWebDragOp(context->actions)); 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tab_contents_->GetBookmarkDragDelegate()) 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_contents_->GetBookmarkDragDelegate()->OnDragOver(bookmark_drag_data_); 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drag_over_time_ = time; 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Pretend we are a drag destination because we don't want to wait for 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the renderer to tell us if we really are or not. 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return TRUE; 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebDragDestGtk::OnDragDataReceived( 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkWidget* sender, GdkDragContext* context, gint x, gint y, 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkSelectionData* data, guint info, guint time) { 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We might get the data from an old get_data() request that we no longer 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // care about. 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (context != context_) 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data_requests_--; 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Decode the data. 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (data->data && data->length > 0) { 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If the source can't provide us with valid data for a requested target, 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // data->data will be NULL. 15472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (data->target == ui::GetAtomForTarget(ui::TEXT_PLAIN)) { 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guchar* text = gtk_selection_data_get_text(data); 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (text) { 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drop_data_->plain_text = 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UTF8ToUTF16(std::string(reinterpret_cast<char*>(text), 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data->length)); 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_free(text); 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 16272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else if (data->target == ui::GetAtomForTarget(ui::TEXT_URI_LIST)) { 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gchar** uris = gtk_selection_data_get_uris(data); 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (uris) { 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drop_data_->url = GURL(); 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (gchar** uri_iter = uris; *uri_iter; uri_iter++) { 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Most file managers populate text/uri-list with file URLs when 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // dragging files. To avoid exposing file system paths to web content, 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // file URLs are never set as the URL content for the drop. 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(estade): Can the filenames have a non-UTF8 encoding? 171513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch GURL url(*uri_iter); 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath file_path; 173513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (url.SchemeIs(chrome::kFileScheme) && 174513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch net::FileURLToFilePath(url, &file_path)) { 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drop_data_->filenames.push_back(UTF8ToUTF16(file_path.value())); 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This is a hack. Some file managers also populate text/plain with 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // a file URL when dragging files, so we clear it to avoid exposing 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // it to the web content. 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drop_data_->plain_text.clear(); 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (!drop_data_->url.is_valid()) { 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Also set the first non-file URL as the URL content for the drop. 182513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch drop_data_->url = url; 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_strfreev(uris); 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 18772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else if (data->target == ui::GetAtomForTarget(ui::TEXT_HTML)) { 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(estade): Can the html have a non-UTF8 encoding? 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drop_data_->text_html = 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UTF8ToUTF16(std::string(reinterpret_cast<char*>(data->data), 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data->length)); 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We leave the base URL empty. 19372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else if (data->target == ui::GetAtomForTarget(ui::NETSCAPE_URL)) { 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string netscape_url(reinterpret_cast<char*>(data->data), 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data->length); 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t split = netscape_url.find_first_of('\n'); 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (split != std::string::npos) { 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drop_data_->url = GURL(netscape_url.substr(0, split)); 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (split < netscape_url.size() - 1) 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drop_data_->url_title = UTF8ToUTF16(netscape_url.substr(split + 1)); 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 20272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else if (data->target == ui::GetAtomForTarget(ui::CHROME_NAMED_URL)) { 20372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ui::ExtractNamedURL(data, &drop_data_->url, &drop_data_->url_title); 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // For CHROME_BOOKMARK_ITEM, we have to handle the case where the drag source 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // doesn't have any data available for us. In this case we try to synthesize a 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // URL bookmark. 210731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Note that bookmark drag data is encoded in the same format for both 211731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // GTK and Views, hence we can share the same logic here. 212731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (data->target == GetBookmarkTargetAtom()) { 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (data->data && data->length > 0) { 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bookmark_drag_data_.ReadFromVector( 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bookmark_utils::GetNodesFromSelection( 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NULL, data, 21772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ui::CHROME_BOOKMARK_ITEM, 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_contents_->profile(), NULL, NULL)); 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bookmark_drag_data_.SetOriginatingProfile(tab_contents_->profile()); 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bookmark_drag_data_.ReadFromTuple(drop_data_->url, 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drop_data_->url_title); 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (data_requests_ == 0) { 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Tell the renderer about the drag. 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // |x| and |y| are seemingly arbitrary at this point. 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_contents_->render_view_host()-> 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DragTargetDragEnter(*drop_data_.get(), 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_util::ClientPoint(widget_), 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_util::ScreenPoint(widget_), 233731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick gtk_util::GdkDragActionToWebDragOp(context->actions)); 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 23572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // This is non-null if tab_contents_ is showing an ExtensionWebUI with 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // support for (at the moment experimental) drag and drop extensions. 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tab_contents_->GetBookmarkDragDelegate()) { 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_contents_->GetBookmarkDragDelegate()->OnDragEnter( 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bookmark_drag_data_); 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drag_over_time_ = time; 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The drag has left our widget; forward this information to the renderer. 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebDragDestGtk::OnDragLeave(GtkWidget* sender, GdkDragContext* context, 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint time) { 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Set |context_| to NULL to make sure we will recognize the next DragMotion 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // as an enter. 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch context_ = NULL; 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drop_data_.reset(); 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // When GTK sends us a drag-drop signal, it is shortly (and synchronously) 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // preceded by a drag-leave. The renderer doesn't like getting the signals 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // in this order so delay telling it about the drag-leave till we are sure 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // we are not getting a drop as well. 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop::current()->PostTask(FROM_HERE, 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch method_factory_.NewRunnableMethod(&WebDragDestGtk::DragLeave)); 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Called by GTK when the user releases the mouse, executing a drop. 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean WebDragDestGtk::OnDragDrop(GtkWidget* sender, GdkDragContext* context, 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gint x, gint y, guint time) { 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Cancel that drag leave! 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch method_factory_.RevokeAll(); 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_contents_->render_view_host()-> 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DragTargetDrop(gtk_util::ClientPoint(widget_), 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_util::ScreenPoint(widget_)); 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 27172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // This is non-null if tab_contents_ is showing an ExtensionWebUI with 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // support for (at the moment experimental) drag and drop extensions. 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tab_contents_->GetBookmarkDragDelegate()) 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_contents_->GetBookmarkDragDelegate()->OnDrop(bookmark_drag_data_); 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The second parameter is just an educated guess as to whether or not the 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // drag succeeded, but at least we will get the drag-end animation right 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // sometimes. 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_drag_finish(context, is_drop_target_, FALSE, time); 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return TRUE; 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 282