Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(333)

Side by Side Diff: chrome/browser/ui/views/tabs/tab_strip.cc

Issue 68133020: Fix dragging supported files to tab strip. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/views/tabs/tab_strip.h" 5 #include "chrome/browser/ui/views/tabs/tab_strip.h"
6 6
7 #if defined(OS_WIN) 7 #if defined(OS_WIN)
8 #include <windowsx.h> 8 #include <windowsx.h>
9 #endif 9 #endif
10 10
11 #include <algorithm> 11 #include <algorithm>
12 #include <iterator> 12 #include <iterator>
13 #include <string> 13 #include <string>
14 #include <vector> 14 #include <vector>
15 15
16 #include "base/compiler_specific.h" 16 #include "base/compiler_specific.h"
17 #include "base/metrics/histogram.h" 17 #include "base/metrics/histogram.h"
18 #include "base/stl_util.h" 18 #include "base/stl_util.h"
19 #include "base/strings/utf_string_conversions.h" 19 #include "base/strings/utf_string_conversions.h"
20 #include "base/task_runner_util.h"
20 #include "chrome/browser/defaults.h" 21 #include "chrome/browser/defaults.h"
22 #include "chrome/browser/profiles/profile.h"
21 #include "chrome/browser/ui/host_desktop.h" 23 #include "chrome/browser/ui/host_desktop.h"
22 #include "chrome/browser/ui/tabs/tab_strip_model.h" 24 #include "chrome/browser/ui/tabs/tab_strip_model.h"
23 #include "chrome/browser/ui/view_ids.h" 25 #include "chrome/browser/ui/view_ids.h"
24 #include "chrome/browser/ui/views/tabs/stacked_tab_strip_layout.h" 26 #include "chrome/browser/ui/views/tabs/stacked_tab_strip_layout.h"
25 #include "chrome/browser/ui/views/tabs/tab.h" 27 #include "chrome/browser/ui/views/tabs/tab.h"
26 #include "chrome/browser/ui/views/tabs/tab_drag_controller.h" 28 #include "chrome/browser/ui/views/tabs/tab_drag_controller.h"
27 #include "chrome/browser/ui/views/tabs/tab_strip_controller.h" 29 #include "chrome/browser/ui/views/tabs/tab_strip_controller.h"
28 #include "chrome/browser/ui/views/tabs/tab_strip_observer.h" 30 #include "chrome/browser/ui/views/tabs/tab_strip_observer.h"
29 #include "chrome/browser/ui/views/touch_uma/touch_uma.h" 31 #include "chrome/browser/ui/views/touch_uma/touch_uma.h"
32 #include "content/public/browser/browser_thread.h"
33 #include "content/public/browser/plugin_service.h"
30 #include "content/public/browser/user_metrics.h" 34 #include "content/public/browser/user_metrics.h"
35 #include "content/public/common/webplugininfo.h"
31 #include "grit/generated_resources.h" 36 #include "grit/generated_resources.h"
32 #include "grit/theme_resources.h" 37 #include "grit/theme_resources.h"
38 #include "ipc/ipc_message.h"
39 #include "net/base/net_util.h"
33 #include "ui/base/accessibility/accessible_view_state.h" 40 #include "ui/base/accessibility/accessible_view_state.h"
34 #include "ui/base/default_theme_provider.h" 41 #include "ui/base/default_theme_provider.h"
35 #include "ui/base/dragdrop/drag_drop_types.h" 42 #include "ui/base/dragdrop/drag_drop_types.h"
36 #include "ui/base/l10n/l10n_util.h" 43 #include "ui/base/l10n/l10n_util.h"
37 #include "ui/base/layout.h" 44 #include "ui/base/layout.h"
38 #include "ui/base/models/list_selection_model.h" 45 #include "ui/base/models/list_selection_model.h"
39 #include "ui/base/resource/resource_bundle.h" 46 #include "ui/base/resource/resource_bundle.h"
40 #include "ui/gfx/animation/animation_container.h" 47 #include "ui/gfx/animation/animation_container.h"
41 #include "ui/gfx/animation/throb_animation.h" 48 #include "ui/gfx/animation/throb_animation.h"
42 #include "ui/gfx/canvas.h" 49 #include "ui/gfx/canvas.h"
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 views::View::ConvertPointToTarget(source, dest, &dest_point); 290 views::View::ConvertPointToTarget(source, dest, &dest_point);
284 return dest->GetTooltipHandlerForPoint(dest_point); 291 return dest->GetTooltipHandlerForPoint(dest_point);
285 } 292 }
286 293
287 TabDragController::EventSource EventSourceFromEvent( 294 TabDragController::EventSource EventSourceFromEvent(
288 const ui::LocatedEvent& event) { 295 const ui::LocatedEvent& event) {
289 return event.IsGestureEvent() ? TabDragController::EVENT_SOURCE_TOUCH : 296 return event.IsGestureEvent() ? TabDragController::EVENT_SOURCE_TOUCH :
290 TabDragController::EVENT_SOURCE_MOUSE; 297 TabDragController::EVENT_SOURCE_MOUSE;
291 } 298 }
292 299
300 // Get the MIME type of the file pointed to by the url. This must be called
301 // from an thread that allows IO.
302 std::string FindURLMimeType(GURL url) {
303 base::FilePath full_path;
304 net::FileURLToFilePath(url, &full_path);
305
306 std::string mime_type;
307 // Get the MIME type based on the file path's extension.
308 // This may use registry or file IO.
309 net::GetMimeTypeFromFile(full_path, &mime_type);
310
311 return mime_type;
312 }
313
293 } // namespace 314 } // namespace
294 315
295 /////////////////////////////////////////////////////////////////////////////// 316 ///////////////////////////////////////////////////////////////////////////////
296 // NewTabButton 317 // NewTabButton
297 // 318 //
298 // A subclass of button that hit-tests to the shape of the new tab button and 319 // A subclass of button that hit-tests to the shape of the new tab button and
299 // does custom drawing. 320 // does custom drawing.
300 321
301 class NewTabButton : public views::ImageButton { 322 class NewTabButton : public views::ImageButton {
302 public: 323 public:
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after
602 // static 623 // static
603 const int TabStrip::kMiniToNonMiniGap = 3; 624 const int TabStrip::kMiniToNonMiniGap = 3;
604 625
605 TabStrip::TabStrip(TabStripController* controller) 626 TabStrip::TabStrip(TabStripController* controller)
606 : controller_(controller), 627 : controller_(controller),
607 newtab_button_(NULL), 628 newtab_button_(NULL),
608 current_unselected_width_(Tab::GetStandardSize().width()), 629 current_unselected_width_(Tab::GetStandardSize().width()),
609 current_selected_width_(Tab::GetStandardSize().width()), 630 current_selected_width_(Tab::GetStandardSize().width()),
610 available_width_for_tabs_(-1), 631 available_width_for_tabs_(-1),
611 in_tab_close_(false), 632 in_tab_close_(false),
633 drag_file_supported_(true),
612 animation_container_(new gfx::AnimationContainer()), 634 animation_container_(new gfx::AnimationContainer()),
613 bounds_animator_(this), 635 bounds_animator_(this),
614 layout_type_(TAB_STRIP_LAYOUT_SHRINK), 636 layout_type_(TAB_STRIP_LAYOUT_SHRINK),
615 adjust_layout_(false), 637 adjust_layout_(false),
616 reset_to_shrink_on_exit_(false), 638 reset_to_shrink_on_exit_(false),
617 mouse_move_count_(0), 639 mouse_move_count_(0),
618 immersive_style_(false) { 640 immersive_style_(false),
641 weak_ptr_factory_(this) {
619 Init(); 642 Init();
620 } 643 }
621 644
622 TabStrip::~TabStrip() { 645 TabStrip::~TabStrip() {
623 FOR_EACH_OBSERVER(TabStripObserver, observers_, 646 FOR_EACH_OBSERVER(TabStripObserver, observers_,
624 TabStripDeleted(this)); 647 TabStripDeleted(this));
625 648
626 // The animations may reference the tabs. Shut down the animation before we 649 // The animations may reference the tabs. Shut down the animation before we
627 // delete the tabs. 650 // delete the tabs.
628 StopAnimating(false); 651 StopAnimating(false);
(...skipping 759 matching lines...) Expand 10 before | Expand all | Expand 10 after
1388 } else { 1411 } else {
1389 needed_width = Tab::GetMinimumSelectedSize().width(); 1412 needed_width = Tab::GetMinimumSelectedSize().width();
1390 } 1413 }
1391 needed_width += new_tab_button_width(); 1414 needed_width += new_tab_button_width();
1392 if (immersive_style_) 1415 if (immersive_style_)
1393 return gfx::Size(needed_width, Tab::GetImmersiveHeight()); 1416 return gfx::Size(needed_width, Tab::GetImmersiveHeight());
1394 return gfx::Size(needed_width, Tab::GetMinimumUnselectedSize().height()); 1417 return gfx::Size(needed_width, Tab::GetMinimumUnselectedSize().height());
1395 } 1418 }
1396 1419
1397 void TabStrip::OnDragEntered(const DropTargetEvent& event) { 1420 void TabStrip::OnDragEntered(const DropTargetEvent& event) {
1421 // Clear information about previous drag operation.
1422 drag_url_ = GURL();
1423 drag_file_supported_ = true;
1424
1425 GURL url;
1426 string16 title;
1427 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
1428 // Cache the URL associated with the current drag.
1429 drag_url_ = url;
1430
1431 // Get the MIME type of the file based on the file path's extension.
1432 // Pass the input URL to be certain which URL the reply is for.
1433 base::PostTaskAndReplyWithResult(
1434 content::BrowserThread::GetBlockingPool(),
1435 FROM_HERE,
1436 base::Bind(&FindURLMimeType, url),
1437 base::Bind(&TabStrip::OnFindURLMimeTypeCompleted,
1438 weak_ptr_factory_.GetWeakPtr(),
1439 url));
1440 }
1441
1398 // Force animations to stop, otherwise it makes the index calculation tricky. 1442 // Force animations to stop, otherwise it makes the index calculation tricky.
1399 StopAnimating(true); 1443 StopAnimating(true);
1400 1444
1401 UpdateDropIndex(event); 1445 UpdateDropIndex(event);
1402 } 1446 }
1403 1447
1404 int TabStrip::OnDragUpdated(const DropTargetEvent& event) { 1448 int TabStrip::OnDragUpdated(const DropTargetEvent& event) {
1405 UpdateDropIndex(event); 1449 UpdateDropIndex(event);
1450
1451 if (!drag_file_supported_)
1452 return ui::DragDropTypes::DRAG_NONE;
1453
1406 return GetDropEffect(event); 1454 return GetDropEffect(event);
1407 } 1455 }
1408 1456
1409 void TabStrip::OnDragExited() { 1457 void TabStrip::OnDragExited() {
1410 SetDropIndex(-1, false); 1458 SetDropIndex(-1, false);
1411 } 1459 }
1412 1460
1413 int TabStrip::OnPerformDrop(const DropTargetEvent& event) { 1461 int TabStrip::OnPerformDrop(const DropTargetEvent& event) {
1414 if (!drop_info_.get()) 1462 if (!drop_info_.get())
1415 return ui::DragDropTypes::DRAG_NONE; 1463 return ui::DragDropTypes::DRAG_NONE;
1416 1464
1417 const int drop_index = drop_info_->drop_index; 1465 const int drop_index = drop_info_->drop_index;
1418 const bool drop_before = drop_info_->drop_before; 1466 const bool drop_before = drop_info_->drop_before;
1419 1467
1420 // Hide the drop indicator. 1468 // Hide the drop indicator.
1421 SetDropIndex(-1, false); 1469 SetDropIndex(-1, false);
1422 1470
1423 GURL url; 1471 GURL url;
1424 string16 title; 1472 string16 title;
1425 if (!event.data().GetURLAndTitle(&url, &title) || !url.is_valid()) 1473 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.
1474 !url.is_valid())
1426 return ui::DragDropTypes::DRAG_NONE; 1475 return ui::DragDropTypes::DRAG_NONE;
1427 1476
1428 controller()->PerformDrop(drop_before, drop_index, url); 1477 controller()->PerformDrop(drop_before, drop_index, url);
1429 1478
1430 return GetDropEffect(event); 1479 return GetDropEffect(event);
1431 } 1480 }
1432 1481
1433 void TabStrip::GetAccessibleState(ui::AccessibleViewState* state) { 1482 void TabStrip::GetAccessibleState(ui::AccessibleViewState* state) {
1434 state->role = ui::AccessibilityTypes::ROLE_PAGETABLIST; 1483 state->role = ui::AccessibilityTypes::ROLE_PAGETABLIST;
1435 } 1484 }
(...skipping 597 matching lines...) Expand 10 before | Expand all | Expand 10 after
2033 GenerateIdealBounds(); 2082 GenerateIdealBounds();
2034 AnimateToIdealBounds(); 2083 AnimateToIdealBounds();
2035 } 2084 }
2036 bounds_animator_.AnimateViewTo(tab, ideal_bounds(tab_data_index)); 2085 bounds_animator_.AnimateViewTo(tab, ideal_bounds(tab_data_index));
2037 // Install a delegate to reset the dragging state when done. We have to leave 2086 // Install a delegate to reset the dragging state when done. We have to leave
2038 // dragging true for the tab otherwise it'll draw beneath the new tab button. 2087 // dragging true for the tab otherwise it'll draw beneath the new tab button.
2039 bounds_animator_.SetAnimationDelegate( 2088 bounds_animator_.SetAnimationDelegate(
2040 tab, new ResetDraggingStateDelegate(tab), true); 2089 tab, new ResetDraggingStateDelegate(tab), true);
2041 } 2090 }
2042 2091
2092 void TabStrip::OnFindURLMimeTypeCompleted(GURL url,
2093 const std::string& mime_type) {
2094 // If this is a reply for the current URL, check if the file is unsupported.
2095 // If the MIME type is empty, we do not have enough info to disallow the drag.
2096 if (url == drag_url_ && !mime_type.empty() &&
2097 !net::IsSupportedMimeType(mime_type)) {
2098 // Check whether there is a plugin that supports the mime type (e.g. PDF).
2099 // TODO(bauerb): This possibly uses stale information, but it's guaranteed
2100 // not to do disk access.
2101 bool allow_wildcard = false;
2102 content::WebPluginInfo plugin;
2103 if (!content::PluginService::GetInstance()->GetPluginInfo(
2104 -1, // process ID
2105 MSG_ROUTING_NONE, // routing ID
2106 controller()->GetProfile()->GetResourceContext(),
2107 url, GURL(), mime_type, allow_wildcard,
2108 NULL, &plugin, NULL))
2109 drag_file_supported_ = false;
2110 }
2111 }
2112
2043 void TabStrip::OwnDragController(TabDragController* controller) { 2113 void TabStrip::OwnDragController(TabDragController* controller) {
2044 // Typically, ReleaseDragController() and OwnDragController() calls are paired 2114 // Typically, ReleaseDragController() and OwnDragController() calls are paired
2045 // via corresponding calls to TabDragController::Detach() and 2115 // via corresponding calls to TabDragController::Detach() and
2046 // TabDragController::Attach(). There is one exception to that rule: when a 2116 // TabDragController::Attach(). There is one exception to that rule: when a
2047 // drag might start, we create a TabDragController that is owned by the 2117 // drag might start, we create a TabDragController that is owned by the
2048 // potential source tabstrip in MaybeStartDrag(). If a drag actually starts, 2118 // potential source tabstrip in MaybeStartDrag(). If a drag actually starts,
2049 // we then call Attach() on the source tabstrip, but since the source tabstrip 2119 // we then call Attach() on the source tabstrip, but since the source tabstrip
2050 // already owns the TabDragController, so we don't need to do anything. 2120 // already owns the TabDragController, so we don't need to do anything.
2051 if (controller != drag_controller_.get()) 2121 if (controller != drag_controller_.get())
2052 drag_controller_.reset(controller); 2122 drag_controller_.reset(controller);
(...skipping 678 matching lines...) Expand 10 before | Expand all | Expand 10 after
2731 #if defined(USE_AURA) 2801 #if defined(USE_AURA)
2732 return chrome::GetHostDesktopTypeForNativeView( 2802 return chrome::GetHostDesktopTypeForNativeView(
2733 GetWidget()->GetNativeView()) == chrome::HOST_DESKTOP_TYPE_ASH; 2803 GetWidget()->GetNativeView()) == chrome::HOST_DESKTOP_TYPE_ASH;
2734 #else 2804 #else
2735 if (ui::GetDisplayLayout() != ui::LAYOUT_TOUCH) 2805 if (ui::GetDisplayLayout() != ui::LAYOUT_TOUCH)
2736 return false; 2806 return false;
2737 #endif 2807 #endif
2738 2808
2739 return true; 2809 return true;
2740 } 2810 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698