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