Fix dragging supported files to tab strip.

Use the inferred MIME type of download items, rather than the server value,
when deciding if the tab strip can allow a drop. Get the MIME type
asynchronously so we don't crash (IO must be allowed in the call to
GetMimeTypeFromFile).

Also check the profile's plugins when determining whether a MIME type is
supported.

Regardless of whether a file is supported, the dragging operation should
still be allowed so that spring-loaded tabs work with file drags.

BUG=274288
R=asanka@chromium.org, sky@chromium.org

Review URL: https://codereview.chromium.org/68133020

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@238253 0039d316-1c4b-4281-b951-d872f2087c98
parent 396b3f09
......@@ -46,15 +46,9 @@ void DragDownloadItem(const content::DownloadItem* download,
const base::FilePath full_path = download->GetTargetFilePath();
data.SetFilename(full_path);
std::string mime_type = download->GetMimeType();
if (mime_type.empty())
net::GetMimeTypeFromFile(full_path, &mime_type);
// Add URL so that we can load supported files when dragged to WebContents.
if (net::IsSupportedMimeType(mime_type)) {
data.SetURL(net::FilePathToFileURL(full_path),
download->GetFileNameToReportUser().LossyDisplayName());
}
data.SetURL(net::FilePathToFileURL(full_path),
download->GetFileNameToReportUser().LossyDisplayName());
#if !defined(TOOLKIT_GTK)
#if defined(USE_AURA)
......
......@@ -7,6 +7,7 @@
#include "base/auto_reset.h"
#include "base/command_line.h"
#include "base/prefs/pref_service.h"
#include "base/task_runner_util.h"
#include "chrome/browser/autocomplete/autocomplete_classifier.h"
#include "chrome/browser/autocomplete/autocomplete_classifier_factory.h"
#include "chrome/browser/autocomplete/autocomplete_match.h"
......@@ -29,9 +30,14 @@
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/webplugininfo.h"
#include "ipc/ipc_message.h"
#include "net/base/net_util.h"
#include "ui/base/layout.h"
#include "ui/base/models/list_selection_model.h"
#include "ui/gfx/image/image.h"
......@@ -79,6 +85,20 @@ TabStripLayoutType DetermineTabStripLayout(
}
}
// Get the MIME type of the file pointed to by the url, based on the file's
// extension. Must be called on a thread that allows IO.
std::string FindURLMimeType(const GURL& url) {
DCHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
base::FilePath full_path;
net::FileURLToFilePath(url, &full_path);
// Get the MIME type based on the filename.
std::string mime_type;
net::GetMimeTypeFromFile(full_path, &mime_type);
return mime_type;
}
} // namespace
class BrowserTabStripController::TabContextMenuContents
......@@ -177,7 +197,8 @@ BrowserTabStripController::BrowserTabStripController(Browser* browser,
: model_(model),
tabstrip_(NULL),
browser_(browser),
hover_tab_selector_(model) {
hover_tab_selector_(model),
weak_ptr_factory_(this) {
model_->AddObserver(this);
local_pref_registrar_.Init(g_browser_process->local_state());
......@@ -401,6 +422,16 @@ void BrowserTabStripController::OnStoppedDraggingTabs() {
immersive_reveal_lock_.reset();
}
void BrowserTabStripController::CheckFileSupported(const GURL& url) {
base::PostTaskAndReplyWithResult(
content::BrowserThread::GetBlockingPool(),
FROM_HERE,
base::Bind(&FindURLMimeType, url),
base::Bind(&BrowserTabStripController::OnFindURLMimeTypeCompleted,
weak_ptr_factory_.GetWeakPtr(),
url));
}
////////////////////////////////////////////////////////////////////////////////
// BrowserTabStripController, TabStripModelObserver implementation:
......@@ -546,3 +577,23 @@ void BrowserTabStripController::UpdateLayoutType() {
browser_->host_desktop_type(), &adjust_layout);
tabstrip_->SetLayoutType(layout_type, adjust_layout);
}
void BrowserTabStripController::OnFindURLMimeTypeCompleted(
const GURL& url,
const std::string& mime_type) {
// Check whether the mime type, if given, is known to be supported or 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.
content::WebPluginInfo plugin;
tabstrip_->FileSupported(
url,
mime_type.empty() ||
net::IsSupportedMimeType(mime_type) ||
content::PluginService::GetInstance()->GetPluginInfo(
-1, // process ID
MSG_ROUTING_NONE, // routing ID
model_->profile()->GetResourceContext(),
url, GURL(), mime_type, false,
NULL, &plugin, NULL));
}
......@@ -74,6 +74,7 @@ class BrowserTabStripController : public TabStripController,
virtual void LayoutTypeMaybeChanged() OVERRIDE;
virtual void OnStartedDraggingTabs() OVERRIDE;
virtual void OnStoppedDraggingTabs() OVERRIDE;
virtual void CheckFileSupported(const GURL& url) OVERRIDE;
// TabStripModelObserver implementation:
virtual void TabInsertedAt(content::WebContents* contents,
......@@ -139,6 +140,11 @@ class BrowserTabStripController : public TabStripController,
// Resets the tabstrips layout type from prefs.
void UpdateLayoutType();
// Notifies the tabstrip whether |url| is supported once a MIME type request
// has completed.
void OnFindURLMimeTypeCompleted(const GURL& url,
const std::string& mime_type);
TabStripModel* model_;
TabStrip* tabstrip_;
......@@ -159,6 +165,8 @@ class BrowserTabStripController : public TabStripController,
PrefChangeRegistrar local_pref_registrar_;
base::WeakPtrFactory<BrowserTabStripController> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(BrowserTabStripController);
};
......
......@@ -124,3 +124,7 @@ void FakeBaseTabStripController::OnStartedDraggingTabs() {
void FakeBaseTabStripController::OnStoppedDraggingTabs() {
}
void FakeBaseTabStripController::CheckFileSupported(const GURL& url) {
tab_strip_->FileSupported(url, true);
}
......@@ -51,6 +51,7 @@ class FakeBaseTabStripController : public TabStripController {
virtual void LayoutTypeMaybeChanged() OVERRIDE;
virtual void OnStartedDraggingTabs() OVERRIDE;
virtual void OnStoppedDraggingTabs() OVERRIDE;
virtual void CheckFileSupported(const GURL& url) OVERRIDE;
private:
TabStrip* tab_strip_;
......
......@@ -992,6 +992,11 @@ void TabStrip::StopAnimating(bool layout) {
DoLayout();
}
void TabStrip::FileSupported(const GURL& url, bool supported) {
if (drop_info_.get() && drop_info_->url == url)
drop_info_->file_supported = supported;
}
const ui::ListSelectionModel& TabStrip::GetSelectionModel() {
return controller_->GetSelectionModel();
}
......@@ -1402,10 +1407,28 @@ void TabStrip::OnDragEntered(const DropTargetEvent& event) {
StopAnimating(true);
UpdateDropIndex(event);
GURL url;
string16 title;
// Check whether the event data includes supported drop data.
if (event.data().GetURLAndTitle(&url, &title) && url.is_valid()) {
drop_info_->url = url;
// For file:// URLs, kick off a MIME type request in case they're dropped.
if (url.SchemeIsFile())
controller()->CheckFileSupported(url);
}
}
int TabStrip::OnDragUpdated(const DropTargetEvent& event) {
// Update the drop index even if the file is unsupported, to allow
// dragging a file to the contents of another tab.
UpdateDropIndex(event);
if (!drop_info_->file_supported)
return ui::DragDropTypes::DRAG_NONE;
return GetDropEffect(event);
}
......@@ -1419,13 +1442,17 @@ int TabStrip::OnPerformDrop(const DropTargetEvent& event) {
const int drop_index = drop_info_->drop_index;
const bool drop_before = drop_info_->drop_before;
const bool file_supported = drop_info_->file_supported;
// Hide the drop indicator.
SetDropIndex(-1, false);
// Do nothing if the file was unsupported or the URL is invalid. The URL may
// have been changed after |drop_info_| was created.
GURL url;
string16 title;
if (!event.data().GetURLAndTitle(&url, &title) || !url.is_valid())
if (!file_supported ||
!event.data().GetURLAndTitle(&url, &title) || !url.is_valid())
return ui::DragDropTypes::DRAG_NONE;
controller()->PerformDrop(drop_before, drop_index, url);
......@@ -2434,7 +2461,8 @@ TabStrip::DropInfo::DropInfo(int drop_index,
views::Widget* context)
: drop_index(drop_index),
drop_before(drop_before),
point_down(point_down) {
point_down(point_down),
file_supported(true) {
arrow_view = new views::ImageView;
arrow_view->SetImage(GetDropArrowImage(point_down));
......
......@@ -182,6 +182,9 @@ class TabStrip : public views::View,
// ongoing this does a layout.
void StopAnimating(bool layout);
// Called to indicate whether the given URL is a supported file.
void FileSupported(const GURL& url, bool supported);
// TabController overrides:
virtual const ui::ListSelectionModel& GetSelectionModel() OVERRIDE;
virtual bool SupportsMultipleSelection() OVERRIDE;
......@@ -295,6 +298,12 @@ class TabStrip : public views::View,
views::Widget* arrow_window;
views::ImageView* arrow_view;
// The URL for the drop event.
GURL url;
// Whether the MIME type of the file pointed to by |url| is supported.
bool file_supported;
private:
DISALLOW_COPY_AND_ASSIGN(DropInfo);
};
......
......@@ -112,6 +112,10 @@ class TabStripController {
// This is also called when the tabs that the user is dragging were detached
// from this tabstrip but the user is still dragging the tabs.
virtual void OnStoppedDraggingTabs() = 0;
// Determines if the file type of the URL is supported. Should invoke
// TabStrip::FileSupported to report the result.
virtual void CheckFileSupported(const GURL& url) = 0;
};
#endif // CHROME_BROWSER_UI_VIEWS_TABS_TAB_STRIP_CONTROLLER_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment