Index: chrome/browser/ui/views/tabs/tab_strip.cc |
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc |
index 8a63d2bf7cb711bac84d85a4fb450ba93f695c90..bd9c4a689165e5fc987cfbc5839ea7493b5d092d 100644 |
--- a/chrome/browser/ui/views/tabs/tab_strip.cc |
+++ b/chrome/browser/ui/views/tabs/tab_strip.cc |
@@ -17,7 +17,9 @@ |
#include "base/metrics/histogram.h" |
#include "base/stl_util.h" |
#include "base/strings/utf_string_conversions.h" |
+#include "base/task_runner_util.h" |
#include "chrome/browser/defaults.h" |
+#include "chrome/browser/profiles/profile.h" |
#include "chrome/browser/ui/host_desktop.h" |
#include "chrome/browser/ui/tabs/tab_strip_model.h" |
#include "chrome/browser/ui/view_ids.h" |
@@ -27,9 +29,14 @@ |
#include "chrome/browser/ui/views/tabs/tab_strip_controller.h" |
#include "chrome/browser/ui/views/tabs/tab_strip_observer.h" |
#include "chrome/browser/ui/views/touch_uma/touch_uma.h" |
+#include "content/public/browser/browser_thread.h" |
+#include "content/public/browser/plugin_service.h" |
#include "content/public/browser/user_metrics.h" |
+#include "content/public/common/webplugininfo.h" |
#include "grit/generated_resources.h" |
#include "grit/theme_resources.h" |
+#include "ipc/ipc_message.h" |
+#include "net/base/net_util.h" |
#include "ui/base/accessibility/accessible_view_state.h" |
#include "ui/base/default_theme_provider.h" |
#include "ui/base/dragdrop/drag_drop_types.h" |
@@ -290,6 +297,20 @@ TabDragController::EventSource EventSourceFromEvent( |
TabDragController::EVENT_SOURCE_MOUSE; |
} |
+// Get the MIME type of the file pointed to by the url. This must be called |
+// from an thread that allows IO. |
+std::string FindURLMimeType(GURL url) { |
+ base::FilePath full_path; |
+ net::FileURLToFilePath(url, &full_path); |
+ |
+ std::string mime_type; |
+ // Get the MIME type based on the file path's extension. |
+ // This may use registry or file IO. |
+ net::GetMimeTypeFromFile(full_path, &mime_type); |
+ |
+ return mime_type; |
+} |
+ |
} // namespace |
/////////////////////////////////////////////////////////////////////////////// |
@@ -609,13 +630,15 @@ TabStrip::TabStrip(TabStripController* controller) |
current_selected_width_(Tab::GetStandardSize().width()), |
available_width_for_tabs_(-1), |
in_tab_close_(false), |
+ drag_file_supported_(true), |
animation_container_(new gfx::AnimationContainer()), |
bounds_animator_(this), |
layout_type_(TAB_STRIP_LAYOUT_SHRINK), |
adjust_layout_(false), |
reset_to_shrink_on_exit_(false), |
mouse_move_count_(0), |
- immersive_style_(false) { |
+ immersive_style_(false), |
+ weak_ptr_factory_(this) { |
Init(); |
} |
@@ -1395,6 +1418,27 @@ gfx::Size TabStrip::GetPreferredSize() { |
} |
void TabStrip::OnDragEntered(const DropTargetEvent& event) { |
+ // Clear information about previous drag operation. |
+ drag_url_ = GURL(); |
+ drag_file_supported_ = true; |
+ |
+ GURL url; |
+ string16 title; |
+ if (event.data().GetURLAndTitle(&url, &title) && url.is_valid()) { |
asanka
2013/11/15 19:15:22
The logic below here only applies to file:// URLs.
sky
2013/11/15 20:46:37
None-the-less there is no point doing the same tes
asanka
2013/11/15 21:01:13
Yup.
michaelpg
2013/11/15 21:08:01
The check here esnures we don't request unnecessar
|
+ // Cache the URL associated with the current drag. |
+ drag_url_ = url; |
+ |
+ // Get the MIME type of the file based on the file path's extension. |
+ // Pass the input URL to be certain which URL the reply is for. |
+ base::PostTaskAndReplyWithResult( |
+ content::BrowserThread::GetBlockingPool(), |
+ FROM_HERE, |
+ base::Bind(&FindURLMimeType, url), |
+ base::Bind(&TabStrip::OnFindURLMimeTypeCompleted, |
+ weak_ptr_factory_.GetWeakPtr(), |
+ url)); |
+ } |
+ |
// Force animations to stop, otherwise it makes the index calculation tricky. |
StopAnimating(true); |
@@ -1403,6 +1447,10 @@ void TabStrip::OnDragEntered(const DropTargetEvent& event) { |
int TabStrip::OnDragUpdated(const DropTargetEvent& event) { |
UpdateDropIndex(event); |
+ |
+ if (!drag_file_supported_) |
+ return ui::DragDropTypes::DRAG_NONE; |
+ |
return GetDropEffect(event); |
} |
@@ -1422,7 +1470,8 @@ int TabStrip::OnPerformDrop(const DropTargetEvent& event) { |
GURL url; |
string16 title; |
- if (!event.data().GetURLAndTitle(&url, &title) || !url.is_valid()) |
+ if (!drag_file_supported_ || !event.data().GetURLAndTitle(&url, &title) || |
sky
2013/11/15 00:48:54
We shouldn't need to check url/title twice.
michaelpg
2013/11/18 23:24:51
Done, as per above.
|
+ !url.is_valid()) |
return ui::DragDropTypes::DRAG_NONE; |
controller()->PerformDrop(drop_before, drop_index, url); |
@@ -2040,6 +2089,27 @@ void TabStrip::StoppedDraggingTab(Tab* tab, bool* is_first_tab) { |
tab, new ResetDraggingStateDelegate(tab), true); |
} |
+void TabStrip::OnFindURLMimeTypeCompleted(GURL url, |
+ const std::string& mime_type) { |
+ // If this is a reply for the current URL, check if the file is unsupported. |
+ // If the MIME type is empty, we do not have enough info to disallow the drag. |
+ if (url == drag_url_ && !mime_type.empty() && |
+ !net::IsSupportedMimeType(mime_type)) { |
+ // Check whether there is a plugin that supports the mime type (e.g. PDF). |
+ // TODO(bauerb): This possibly uses stale information, but it's guaranteed |
+ // not to do disk access. |
+ bool allow_wildcard = false; |
+ content::WebPluginInfo plugin; |
+ if (!content::PluginService::GetInstance()->GetPluginInfo( |
+ -1, // process ID |
+ MSG_ROUTING_NONE, // routing ID |
+ controller()->GetProfile()->GetResourceContext(), |
+ url, GURL(), mime_type, allow_wildcard, |
+ NULL, &plugin, NULL)) |
+ drag_file_supported_ = false; |
+ } |
+} |
+ |
void TabStrip::OwnDragController(TabDragController* controller) { |
// Typically, ReleaseDragController() and OwnDragController() calls are paired |
// via corresponding calls to TabDragController::Detach() and |