Home | History | Annotate | Download | only in frame
      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 
     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 
     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 
     38 bool BrowserRootView::AreDropTypesRequired() {
     39   return true;
     40 }
     41 
     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 
     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 
     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 
     79 void BrowserRootView::OnDragExited() {
     80   if (forwarding_to_tab_strip_) {
     81     forwarding_to_tab_strip_ = false;
     82     tabstrip()->OnDragExited();
     83   }
     84 }
     85 
     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 
    112 void BrowserRootView::GetAccessibleState(ui::AccessibleViewState* state) {
    113   RootView::GetAccessibleState(state);
    114   state->name = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
    115 }
    116 
    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 
    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 
    139 AbstractTabStripView* BrowserRootView::tabstrip() const {
    140   return browser_view_->tabstrip();
    141 }
    142 
    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