diff options
8 files changed, 111 insertions, 11 deletions
diff --git a/chrome/browser/download/drag_download_item_views.cc b/chrome/browser/download/drag_download_item_views.cc index 7b94718..e7e5df5 100644 --- a/chrome/browser/download/drag_download_item_views.cc +++ b/chrome/browser/download/drag_download_item_views.cc @@ -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) diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc index 90083b0..0db3239 100644 --- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc +++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc @@ -7,6 +7,8 @@ #include "base/auto_reset.h" #include "base/command_line.h" #include "base/prefs/pref_service.h" +#include "base/task_runner_util.h" +#include "base/threading/sequenced_worker_pool.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 +31,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 +86,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 +198,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 +423,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 +578,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)); +} diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h index 06da492..35e8940 100644 --- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h +++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h @@ -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); }; diff --git a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc index 2ac9e82d..1489ac2 100644 --- a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc +++ b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc @@ -124,3 +124,7 @@ void FakeBaseTabStripController::OnStartedDraggingTabs() { void FakeBaseTabStripController::OnStoppedDraggingTabs() { } + +void FakeBaseTabStripController::CheckFileSupported(const GURL& url) { + tab_strip_->FileSupported(url, true); +} diff --git a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h index 68a4b39..374cf58 100644 --- a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h +++ b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h @@ -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_; diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc index 94b1afe..eafc48d 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.cc +++ b/chrome/browser/ui/views/tabs/tab_strip.cc @@ -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)); diff --git a/chrome/browser/ui/views/tabs/tab_strip.h b/chrome/browser/ui/views/tabs/tab_strip.h index 8de46e8..7e01033 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.h +++ b/chrome/browser/ui/views/tabs/tab_strip.h @@ -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); }; diff --git a/chrome/browser/ui/views/tabs/tab_strip_controller.h b/chrome/browser/ui/views/tabs/tab_strip_controller.h index afe7a23..95940f11 100644 --- a/chrome/browser/ui/views/tabs/tab_strip_controller.h +++ b/chrome/browser/ui/views/tabs/tab_strip_controller.h @@ -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_ |