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 |