Home | History | Annotate | Download | only in omnibox
      1 // Copyright 2013 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/omnibox/omnibox_controller.h"
      6 
      7 #include "base/metrics/histogram.h"
      8 #include "chrome/browser/autocomplete/autocomplete_classifier.h"
      9 #include "chrome/browser/autocomplete/autocomplete_match.h"
     10 #include "chrome/browser/autocomplete/search_provider.h"
     11 #include "chrome/browser/net/predictor.h"
     12 #include "chrome/browser/predictors/autocomplete_action_predictor.h"
     13 #include "chrome/browser/prerender/prerender_field_trial.h"
     14 #include "chrome/browser/prerender/prerender_manager.h"
     15 #include "chrome/browser/prerender/prerender_manager_factory.h"
     16 #include "chrome/browser/profiles/profile.h"
     17 #include "chrome/browser/search/search.h"
     18 #include "chrome/browser/ui/omnibox/omnibox_edit_controller.h"
     19 #include "chrome/browser/ui/omnibox/omnibox_edit_model.h"
     20 #include "chrome/browser/ui/omnibox/omnibox_popup_model.h"
     21 #include "chrome/browser/ui/omnibox/omnibox_popup_view.h"
     22 #include "extensions/common/constants.h"
     23 #include "ui/gfx/rect.h"
     24 
     25 
     26 OmniboxController::OmniboxController(OmniboxEditModel* omnibox_edit_model,
     27                                      Profile* profile)
     28     : omnibox_edit_model_(omnibox_edit_model),
     29       profile_(profile) {
     30   autocomplete_controller_.reset(new AutocompleteController(profile, this,
     31       chrome::IsInstantExtendedAPIEnabled() ?
     32           AutocompleteClassifier::kInstantExtendedOmniboxProviders :
     33           AutocompleteClassifier::kDefaultOmniboxProviders));
     34 }
     35 
     36 OmniboxController::~OmniboxController() {
     37 }
     38 
     39 void OmniboxController::StartAutocomplete(
     40     string16 user_text,
     41     size_t cursor_position,
     42     const GURL& current_url,
     43     AutocompleteInput::PageClassification current_page_classification,
     44     bool prevent_inline_autocomplete,
     45     bool prefer_keyword,
     46     bool allow_exact_keyword_match) const {
     47   ClearPopupKeywordMode();
     48   popup_->SetHoveredLine(OmniboxPopupModel::kNoMatch);
     49 
     50   // We don't explicitly clear OmniboxPopupModel::manually_selected_match, as
     51   // Start ends up invoking OmniboxPopupModel::OnResultChanged which clears it.
     52   autocomplete_controller_->Start(AutocompleteInput(
     53       user_text, cursor_position, string16(), current_url,
     54       current_page_classification, prevent_inline_autocomplete,
     55       prefer_keyword, allow_exact_keyword_match,
     56       AutocompleteInput::ALL_MATCHES));
     57 }
     58 
     59 void OmniboxController::OnResultChanged(bool default_match_changed) {
     60   const bool was_open = popup_->IsOpen();
     61   if (default_match_changed) {
     62     // The default match has changed, we need to let the OmniboxEditModel know
     63     // about new inline autocomplete text (blue highlight).
     64     const AutocompleteResult& result = this->result();
     65     const AutocompleteResult::const_iterator match(result.default_match());
     66     if (match != result.end()) {
     67       current_match_ = *match;
     68       if (!prerender::IsOmniboxEnabled(profile_))
     69         DoPreconnect(*match);
     70       omnibox_edit_model_->OnCurrentMatchChanged();
     71     } else {
     72       InvalidateCurrentMatch();
     73       popup_->OnResultChanged();
     74       omnibox_edit_model_->OnPopupDataChanged(string16(), NULL, string16(),
     75                                               false);
     76     }
     77   } else {
     78     popup_->OnResultChanged();
     79   }
     80 
     81   if (!popup_->IsOpen() && was_open) {
     82     // Accept the temporary text as the user text, because it makes little sense
     83     // to have temporary text when the popup is closed.
     84     omnibox_edit_model_->AcceptTemporaryTextAsUserText();
     85   }
     86 }
     87 
     88 void OmniboxController::InvalidateCurrentMatch() {
     89   current_match_ = AutocompleteMatch();
     90 }
     91 
     92 void OmniboxController::ClearPopupKeywordMode() const {
     93   if (popup_->IsOpen() &&
     94       popup_->selected_line_state() == OmniboxPopupModel::KEYWORD)
     95     popup_->SetSelectedLineState(OmniboxPopupModel::NORMAL);
     96 }
     97 
     98 void OmniboxController::DoPreconnect(const AutocompleteMatch& match) {
     99   if (!match.destination_url.SchemeIs(extensions::kExtensionScheme)) {
    100     // Warm up DNS Prefetch cache, or preconnect to a search service.
    101     UMA_HISTOGRAM_ENUMERATION("Autocomplete.MatchType", match.type,
    102                               AutocompleteMatchType::NUM_TYPES);
    103     if (profile_->GetNetworkPredictor()) {
    104       profile_->GetNetworkPredictor()->AnticipateOmniboxUrl(
    105           match.destination_url,
    106           predictors::AutocompleteActionPredictor::IsPreconnectable(match));
    107     }
    108     // We could prefetch the alternate nav URL, if any, but because there
    109     // can be many of these as a user types an initial series of characters,
    110     // the OS DNS cache could suffer eviction problems for minimal gain.
    111   }
    112 }
    113