Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |