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