browser_root_view.cc revision 7d4cd473f85ac64c3747c96c277f9e506a0d2246
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 3// found in the LICENSE file. 4 5#include "chrome/browser/ui/views/frame/browser_root_view.h" 6 7#include "base/auto_reset.h" 8#include "base/strings/utf_string_conversions.h" 9#include "chrome/browser/autocomplete/autocomplete_classifier.h" 10#include "chrome/browser/autocomplete/autocomplete_classifier_factory.h" 11#include "chrome/browser/autocomplete/autocomplete_match.h" 12#include "chrome/browser/profiles/profile.h" 13#include "chrome/browser/ui/omnibox/location_bar.h" 14#include "chrome/browser/ui/views/frame/browser_frame.h" 15#include "chrome/browser/ui/views/frame/browser_view.h" 16#include "chrome/browser/ui/views/tabs/tab_strip.h" 17#include "chrome/common/chrome_notification_types.h" 18#include "grit/chromium_strings.h" 19#include "ui/base/accessibility/accessible_view_state.h" 20#include "ui/base/dragdrop/drag_drop_types.h" 21#include "ui/base/dragdrop/os_exchange_data.h" 22#include "ui/base/l10n/l10n_util.h" 23 24// static 25const char BrowserRootView::kViewClassName[] = 26 "browser/ui/views/frame/BrowserRootView"; 27 28BrowserRootView::BrowserRootView(BrowserView* browser_view, 29 views::Widget* widget) 30 : views::internal::RootView(widget), 31 browser_view_(browser_view), 32 forwarding_to_tab_strip_(false) { } 33 34bool BrowserRootView::GetDropFormats( 35 int* formats, 36 std::set<ui::OSExchangeData::CustomFormat>* custom_formats) { 37 if (tabstrip() && tabstrip()->visible()) { 38 *formats = ui::OSExchangeData::URL | ui::OSExchangeData::STRING; 39 return true; 40 } 41 return false; 42} 43 44bool BrowserRootView::AreDropTypesRequired() { 45 return true; 46} 47 48bool BrowserRootView::CanDrop(const ui::OSExchangeData& data) { 49 if (!tabstrip() || !tabstrip()->visible()) 50 return false; 51 52 // If there is a URL, we'll allow the drop. 53 if (data.HasURL()) 54 return true; 55 56 // If there isn't a URL, see if we can 'paste and go'. 57 return GetPasteAndGoURL(data, NULL); 58} 59 60void BrowserRootView::OnDragEntered(const ui::DropTargetEvent& event) { 61 if (ShouldForwardToTabStrip(event)) { 62 forwarding_to_tab_strip_ = true; 63 scoped_ptr<ui::DropTargetEvent> mapped_event( 64 MapEventToTabStrip(event, event.data())); 65 tabstrip()->OnDragEntered(*mapped_event.get()); 66 } 67} 68 69int BrowserRootView::OnDragUpdated(const ui::DropTargetEvent& event) { 70 if (ShouldForwardToTabStrip(event)) { 71 scoped_ptr<ui::DropTargetEvent> mapped_event( 72 MapEventToTabStrip(event, event.data())); 73 if (!forwarding_to_tab_strip_) { 74 tabstrip()->OnDragEntered(*mapped_event.get()); 75 forwarding_to_tab_strip_ = true; 76 } 77 return tabstrip()->OnDragUpdated(*mapped_event.get()); 78 } else if (forwarding_to_tab_strip_) { 79 forwarding_to_tab_strip_ = false; 80 tabstrip()->OnDragExited(); 81 } 82 return ui::DragDropTypes::DRAG_NONE; 83} 84 85void BrowserRootView::OnDragExited() { 86 if (forwarding_to_tab_strip_) { 87 forwarding_to_tab_strip_ = false; 88 tabstrip()->OnDragExited(); 89 } 90} 91 92int BrowserRootView::OnPerformDrop(const ui::DropTargetEvent& event) { 93 if (!forwarding_to_tab_strip_) 94 return ui::DragDropTypes::DRAG_NONE; 95 96 // Extract the URL and create a new ui::OSExchangeData containing the URL. We 97 // do this as the TabStrip doesn't know about the autocomplete edit and needs 98 // to know about it to handle 'paste and go'. 99 GURL url; 100 string16 title; 101 ui::OSExchangeData mapped_data; 102 if (!event.data().GetURLAndTitle(&url, &title) || !url.is_valid()) { 103 // The url isn't valid. Use the paste and go url. 104 if (GetPasteAndGoURL(event.data(), &url)) 105 mapped_data.SetURL(url, string16()); 106 // else case: couldn't extract a url or 'paste and go' url. This ends up 107 // passing through an ui::OSExchangeData with nothing in it. We need to do 108 // this so that the tab strip cleans up properly. 109 } else { 110 mapped_data.SetURL(url, string16()); 111 } 112 forwarding_to_tab_strip_ = false; 113 scoped_ptr<ui::DropTargetEvent> mapped_event( 114 MapEventToTabStrip(event, mapped_data)); 115 return tabstrip()->OnPerformDrop(*mapped_event); 116} 117 118const char* BrowserRootView::GetClassName() const { 119 return kViewClassName; 120} 121 122bool BrowserRootView::ShouldForwardToTabStrip( 123 const ui::DropTargetEvent& event) { 124 if (!tabstrip()->visible()) 125 return false; 126 127 // Allow the drop as long as the mouse is over the tabstrip or vertically 128 // before it. 129 gfx::Point tab_loc_in_host; 130 ConvertPointToTarget(tabstrip(), this, &tab_loc_in_host); 131 return event.y() < tab_loc_in_host.y() + tabstrip()->height(); 132} 133 134ui::DropTargetEvent* BrowserRootView::MapEventToTabStrip( 135 const ui::DropTargetEvent& event, 136 const ui::OSExchangeData& data) { 137 gfx::Point tab_strip_loc(event.location()); 138 ConvertPointToTarget(this, tabstrip(), &tab_strip_loc); 139 return new ui::DropTargetEvent(data, tab_strip_loc, tab_strip_loc, 140 event.source_operations()); 141} 142 143TabStrip* BrowserRootView::tabstrip() const { 144 return browser_view_->tabstrip(); 145} 146 147bool BrowserRootView::GetPasteAndGoURL(const ui::OSExchangeData& data, 148 GURL* url) { 149 if (!data.HasString()) 150 return false; 151 152 string16 text; 153 if (!data.GetString(&text) || text.empty()) 154 return false; 155 text = AutocompleteMatch::SanitizeString(text); 156 157 AutocompleteMatch match; 158 AutocompleteClassifierFactory::GetForProfile( 159 browser_view_->browser()->profile())->Classify(text, false, false, &match, 160 NULL); 161 if (!match.destination_url.is_valid()) 162 return false; 163 164 if (url) 165 *url = match.destination_url; 166 return true; 167} 168