browser_root_view.cc revision dc0f95d653279beabeb9817299e2902918ba123e
172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/views/frame/browser_root_view.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
73f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/utf_string_conversions.h"
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/autocomplete/autocomplete.h"
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/autocomplete/autocomplete_classifier.h"
10513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/browser/autocomplete/autocomplete_match.h"
1121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h"
1221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/omnibox/location_bar.h"
1321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/views/frame/browser_frame.h"
1472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/views/frame/browser_view.h"
1521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/views/tabs/tab_strip.h"
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/chromium_strings.h"
1772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/dragdrop/drag_drop_types.h"
1872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/dragdrop/os_exchange_data.h"
1972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h"
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBrowserRootView::BrowserRootView(BrowserView* browser_view,
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 views::Widget* widget)
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : views::RootView(widget),
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      browser_view_(browser_view),
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      forwarding_to_tab_strip_(false) {
2672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  SetAccessibleName(l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BrowserRootView::GetDropFormats(
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      int* formats,
3172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      std::set<ui::OSExchangeData::CustomFormat>* custom_formats) {
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (tabstrip() && tabstrip()->IsVisible() && !tabstrip()->IsAnimating()) {
3372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    *formats = ui::OSExchangeData::URL | ui::OSExchangeData::STRING;
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return false;
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BrowserRootView::AreDropTypesRequired() {
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool BrowserRootView::CanDrop(const ui::OSExchangeData& data) {
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!tabstrip() || !tabstrip()->IsVisible() || tabstrip()->IsAnimating())
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If there is a URL, we'll allow the drop.
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (data.HasURL())
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If there isn't a URL, see if we can 'paste and go'.
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return GetPasteAndGoURL(data, NULL);
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserRootView::OnDragEntered(const views::DropTargetEvent& event) {
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (ShouldForwardToTabStrip(event)) {
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    forwarding_to_tab_strip_ = true;
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<views::DropTargetEvent> mapped_event(
5972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        MapEventToTabStrip(event, event.data()));
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    tabstrip()->OnDragEntered(*mapped_event.get());
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BrowserRootView::OnDragUpdated(const views::DropTargetEvent& event) {
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (ShouldForwardToTabStrip(event)) {
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<views::DropTargetEvent> mapped_event(
6772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        MapEventToTabStrip(event, event.data()));
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!forwarding_to_tab_strip_) {
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      tabstrip()->OnDragEntered(*mapped_event.get());
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      forwarding_to_tab_strip_ = true;
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return tabstrip()->OnDragUpdated(*mapped_event.get());
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (forwarding_to_tab_strip_) {
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    forwarding_to_tab_strip_ = false;
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    tabstrip()->OnDragExited();
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
7772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return ui::DragDropTypes::DRAG_NONE;
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserRootView::OnDragExited() {
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (forwarding_to_tab_strip_) {
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    forwarding_to_tab_strip_ = false;
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    tabstrip()->OnDragExited();
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BrowserRootView::OnPerformDrop(const views::DropTargetEvent& event) {
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!forwarding_to_tab_strip_)
8972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return ui::DragDropTypes::DRAG_NONE;
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Extract the URL and create a new ui::OSExchangeData containing the URL. We
9272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // do this as the TabStrip doesn't know about the autocomplete edit and needs
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // to know about it to handle 'paste and go'.
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL url;
95dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  string16 title;
9672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ui::OSExchangeData mapped_data;
9772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!event.data().GetURLAndTitle(&url, &title) || !url.is_valid()) {
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // The url isn't valid. Use the paste and go url.
9972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (GetPasteAndGoURL(event.data(), &url))
100dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      mapped_data.SetURL(url, string16());
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // else case: couldn't extract a url or 'paste and go' url. This ends up
10272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // passing through an ui::OSExchangeData with nothing in it. We need to do
10372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // this so that the tab strip cleans up properly.
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
105dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    mapped_data.SetURL(url, string16());
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  forwarding_to_tab_strip_ = false;
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<views::DropTargetEvent> mapped_event(
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      MapEventToTabStrip(event, mapped_data));
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return tabstrip()->OnPerformDrop(*mapped_event);
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BrowserRootView::ShouldForwardToTabStrip(
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const views::DropTargetEvent& event) {
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!tabstrip()->IsVisible())
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Allow the drop as long as the mouse is over the tabstrip or vertically
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // before it.
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Point tab_loc_in_host;
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ConvertPointToView(tabstrip(), this, &tab_loc_in_host);
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return event.y() < tab_loc_in_host.y() + tabstrip()->height();
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochviews::DropTargetEvent* BrowserRootView::MapEventToTabStrip(
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const views::DropTargetEvent& event,
12772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const ui::OSExchangeData& data) {
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Point tab_strip_loc(event.location());
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ConvertPointToView(this, tabstrip(), &tab_strip_loc);
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return new views::DropTargetEvent(data, tab_strip_loc.x(),
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    tab_strip_loc.y(),
13272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                    event.source_operations());
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBaseTabStrip* BrowserRootView::tabstrip() const {
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return browser_view_->tabstrip();
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
13972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool BrowserRootView::GetPasteAndGoURL(const ui::OSExchangeData& data,
14072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                       GURL* url) {
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!data.HasString())
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
144dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  string16 text;
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!data.GetString(&text) || text.empty())
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AutocompleteMatch match;
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  browser_view_->browser()->profile()->GetAutocompleteClassifier()->Classify(
150dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      text, string16(), false, &match, NULL);
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!match.destination_url.is_valid())
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (url)
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    *url = match.destination_url;
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
158