| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ui/omnibox/omnibox_controller.h" | 5 #include "chrome/browser/ui/omnibox/omnibox_controller.h" |
| 6 | 6 |
| 7 #include "base/metrics/histogram.h" | 7 #include "base/metrics/histogram.h" |
| 8 #include "chrome/browser/autocomplete/autocomplete_classifier.h" | 8 #include "chrome/browser/autocomplete/autocomplete_classifier.h" |
| 9 #include "chrome/browser/autocomplete/autocomplete_match.h" | 9 #include "chrome/browser/autocomplete/autocomplete_match.h" |
| 10 #include "chrome/browser/autocomplete/search_provider.h" |
| 10 #include "chrome/browser/net/predictor.h" | 11 #include "chrome/browser/net/predictor.h" |
| 11 #include "chrome/browser/predictors/autocomplete_action_predictor.h" | 12 #include "chrome/browser/predictors/autocomplete_action_predictor.h" |
| 12 #include "chrome/browser/prerender/prerender_field_trial.h" | 13 #include "chrome/browser/prerender/prerender_field_trial.h" |
| 13 #include "chrome/browser/prerender/prerender_manager.h" | 14 #include "chrome/browser/prerender/prerender_manager.h" |
| 14 #include "chrome/browser/prerender/prerender_manager_factory.h" | 15 #include "chrome/browser/prerender/prerender_manager_factory.h" |
| 15 #include "chrome/browser/profiles/profile.h" | 16 #include "chrome/browser/profiles/profile.h" |
| 16 #include "chrome/browser/search/search.h" | 17 #include "chrome/browser/search/search.h" |
| 17 #include "chrome/browser/ui/omnibox/omnibox_edit_controller.h" | 18 #include "chrome/browser/ui/omnibox/omnibox_edit_controller.h" |
| 18 #include "chrome/browser/ui/omnibox/omnibox_edit_model.h" | 19 #include "chrome/browser/ui/omnibox/omnibox_edit_model.h" |
| 19 #include "chrome/browser/ui/omnibox/omnibox_popup_model.h" | 20 #include "chrome/browser/ui/omnibox/omnibox_popup_model.h" |
| (...skipping 11 matching lines...) Expand all Loading... |
| 31 profile_(profile) { | 32 profile_(profile) { |
| 32 autocomplete_controller_.reset(new AutocompleteController(profile, this, | 33 autocomplete_controller_.reset(new AutocompleteController(profile, this, |
| 33 chrome::IsInstantExtendedAPIEnabled() ? | 34 chrome::IsInstantExtendedAPIEnabled() ? |
| 34 AutocompleteClassifier::kInstantExtendedOmniboxProviders : | 35 AutocompleteClassifier::kInstantExtendedOmniboxProviders : |
| 35 AutocompleteClassifier::kDefaultOmniboxProviders)); | 36 AutocompleteClassifier::kDefaultOmniboxProviders)); |
| 36 } | 37 } |
| 37 | 38 |
| 38 OmniboxController::~OmniboxController() { | 39 OmniboxController::~OmniboxController() { |
| 39 } | 40 } |
| 40 | 41 |
| 42 void OmniboxController::StartAutocomplete( |
| 43 string16 user_text, |
| 44 size_t cursor_position, |
| 45 bool prevent_inline_autocomplete, |
| 46 bool prefer_keyword, |
| 47 bool allow_exact_keyword_match) const { |
| 48 ClearPopupKeywordMode(); |
| 49 popup_->SetHoveredLine(OmniboxPopupModel::kNoMatch); |
| 50 |
| 51 if (GetInstantController()) { |
| 52 GetInstantController()->OnAutocompleteStart(); |
| 53 // If the embedded page for InstantExtended is fetching its own suggestions, |
| 54 // suppress search suggestions from SearchProvider. We still need |
| 55 // SearchProvider to run for FinalizeInstantQuery. |
| 56 // TODO(dcblack): Once we are done refactoring the omnibox so we don't need |
| 57 // to use FinalizeInstantQuery anymore, we can take out this check and |
| 58 // remove this provider from kInstantExtendedOmniboxProviders. |
| 59 if (GetInstantController()->WillFetchCompletions()) |
| 60 autocomplete_controller_->search_provider()->SuppressSearchSuggestions(); |
| 61 } |
| 62 |
| 63 // We don't explicitly clear OmniboxPopupModel::manually_selected_match, as |
| 64 // Start ends up invoking OmniboxPopupModel::OnResultChanged which clears it. |
| 65 autocomplete_controller_->Start(AutocompleteInput( |
| 66 user_text, cursor_position, string16(), GURL(), |
| 67 prevent_inline_autocomplete, prefer_keyword, allow_exact_keyword_match, |
| 68 AutocompleteInput::ALL_MATCHES)); |
| 69 } |
| 70 |
| 41 void OmniboxController::OnResultChanged(bool default_match_changed) { | 71 void OmniboxController::OnResultChanged(bool default_match_changed) { |
| 42 // TODO(beaudoin): There should be no need to access the popup when using | 72 // TODO(beaudoin): There should be no need to access the popup when using |
| 43 // instant extended, remove this reference. | 73 // instant extended, remove this reference. |
| 44 const bool was_open = popup_->IsOpen(); | 74 const bool was_open = popup_->IsOpen(); |
| 45 if (default_match_changed) { | 75 if (default_match_changed) { |
| 46 // The default match has changed, we need to let the OmniboxEditModel know | 76 // The default match has changed, we need to let the OmniboxEditModel know |
| 47 // about new inline autocomplete text (blue highlight). | 77 // about new inline autocomplete text (blue highlight). |
| 48 string16 inline_autocomplete_text; | 78 string16 inline_autocomplete_text; |
| 49 string16 keyword; | 79 string16 keyword; |
| 50 bool is_keyword_hint = false; | 80 bool is_keyword_hint = false; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 72 omnibox_edit_model_->OnPopupDataChanged(inline_autocomplete_text, NULL, | 102 omnibox_edit_model_->OnPopupDataChanged(inline_autocomplete_text, NULL, |
| 73 keyword, is_keyword_hint); | 103 keyword, is_keyword_hint); |
| 74 } else { | 104 } else { |
| 75 popup_->OnResultChanged(); | 105 popup_->OnResultChanged(); |
| 76 } | 106 } |
| 77 | 107 |
| 78 if (popup_->IsOpen()) { | 108 if (popup_->IsOpen()) { |
| 79 // The popup size may have changed, let instant know. | 109 // The popup size may have changed, let instant know. |
| 80 OnPopupBoundsChanged(popup_->view()->GetTargetBounds()); | 110 OnPopupBoundsChanged(popup_->view()->GetTargetBounds()); |
| 81 | 111 |
| 82 InstantController* instant = | 112 if (GetInstantController() && !omnibox_edit_model_->in_revert()) { |
| 83 omnibox_edit_model_->controller()->GetInstant(); | 113 GetInstantController()->HandleAutocompleteResults( |
| 84 if (instant && !omnibox_edit_model_->in_revert()) { | 114 *autocomplete_controller_->providers(), |
| 85 instant->HandleAutocompleteResults( | 115 autocomplete_controller_->result()); |
| 86 *autocomplete_controller()->providers(), | |
| 87 autocomplete_controller()->result()); | |
| 88 } | 116 } |
| 89 } else if (was_open) { | 117 } else if (was_open) { |
| 90 // Accept the temporary text as the user text, because it makes little sense | 118 // Accept the temporary text as the user text, because it makes little sense |
| 91 // to have temporary text when the popup is closed. | 119 // to have temporary text when the popup is closed. |
| 92 omnibox_edit_model_->AcceptTemporaryTextAsUserText(); | 120 omnibox_edit_model_->AcceptTemporaryTextAsUserText(); |
| 93 // The popup has been closed, let instant know. | 121 // The popup has been closed, let instant know. |
| 94 OnPopupBoundsChanged(gfx::Rect()); | 122 OnPopupBoundsChanged(gfx::Rect()); |
| 95 } | 123 } |
| 96 } | 124 } |
| 97 | 125 |
| 126 bool OmniboxController::DoInstant(const AutocompleteMatch& match, |
| 127 string16 user_text, |
| 128 string16 full_text, |
| 129 size_t selection_start, |
| 130 size_t selection_end, |
| 131 bool user_input_in_progress, |
| 132 bool in_escape_handler, |
| 133 bool just_deleted_text, |
| 134 bool keyword_is_selected) { |
| 135 if (!GetInstantController()) |
| 136 return false; |
| 137 |
| 138 // Remove "?" if we're in forced query mode. |
| 139 AutocompleteInput::RemoveForcedQueryStringIfNecessary( |
| 140 autocomplete_controller_->input().type(), &user_text); |
| 141 AutocompleteInput::RemoveForcedQueryStringIfNecessary( |
| 142 autocomplete_controller_->input().type(), &full_text); |
| 143 return GetInstantController()->Update( |
| 144 match, user_text, full_text, selection_start, selection_end, |
| 145 UseVerbatimInstant(just_deleted_text), user_input_in_progress, |
| 146 popup_->IsOpen(), in_escape_handler, keyword_is_selected); |
| 147 } |
| 148 |
| 98 void OmniboxController::ClearPopupKeywordMode() const { | 149 void OmniboxController::ClearPopupKeywordMode() const { |
| 99 if (popup_->IsOpen() && | 150 if (popup_->IsOpen() && |
| 100 popup_->selected_line_state() == OmniboxPopupModel::KEYWORD) | 151 popup_->selected_line_state() == OmniboxPopupModel::KEYWORD) |
| 101 popup_->SetSelectedLineState(OmniboxPopupModel::NORMAL); | 152 popup_->SetSelectedLineState(OmniboxPopupModel::NORMAL); |
| 102 } | 153 } |
| 103 | 154 |
| 104 void OmniboxController::DoPreconnect(const AutocompleteMatch& match) { | 155 void OmniboxController::DoPreconnect(const AutocompleteMatch& match) { |
| 105 if (!match.destination_url.SchemeIs(extensions::kExtensionScheme)) { | 156 if (!match.destination_url.SchemeIs(extensions::kExtensionScheme)) { |
| 106 // Warm up DNS Prefetch cache, or preconnect to a search service. | 157 // Warm up DNS Prefetch cache, or preconnect to a search service. |
| 107 UMA_HISTOGRAM_ENUMERATION("Autocomplete.MatchType", match.type, | 158 UMA_HISTOGRAM_ENUMERATION("Autocomplete.MatchType", match.type, |
| 108 AutocompleteMatchType::NUM_TYPES); | 159 AutocompleteMatchType::NUM_TYPES); |
| 109 if (profile_->GetNetworkPredictor()) { | 160 if (profile_->GetNetworkPredictor()) { |
| 110 profile_->GetNetworkPredictor()->AnticipateOmniboxUrl( | 161 profile_->GetNetworkPredictor()->AnticipateOmniboxUrl( |
| 111 match.destination_url, | 162 match.destination_url, |
| 112 AutocompleteActionPredictor::IsPreconnectable(match)); | 163 AutocompleteActionPredictor::IsPreconnectable(match)); |
| 113 } | 164 } |
| 114 // We could prefetch the alternate nav URL, if any, but because there | 165 // We could prefetch the alternate nav URL, if any, but because there |
| 115 // can be many of these as a user types an initial series of characters, | 166 // can be many of these as a user types an initial series of characters, |
| 116 // the OS DNS cache could suffer eviction problems for minimal gain. | 167 // the OS DNS cache could suffer eviction problems for minimal gain. |
| 117 } | 168 } |
| 118 } | 169 } |
| 119 | 170 |
| 120 void OmniboxController::OnPopupBoundsChanged(const gfx::Rect& bounds) { | 171 void OmniboxController::OnPopupBoundsChanged(const gfx::Rect& bounds) { |
| 121 InstantController* instant = omnibox_edit_model_->controller()->GetInstant(); | 172 if (GetInstantController()) |
| 122 if (instant) | 173 GetInstantController()->SetPopupBounds(bounds); |
| 123 instant->SetPopupBounds(bounds); | |
| 124 } | 174 } |
| 175 |
| 176 bool OmniboxController::UseVerbatimInstant(bool just_deleted_text) const { |
| 177 #if defined(OS_MACOSX) |
| 178 // TODO(suzhe): Fix Mac port to display Instant suggest in a separated NSView, |
| 179 // so that we can display Instant suggest along with composition text. |
| 180 const AutocompleteInput& input = autocomplete_controller_->input(); |
| 181 if (input.prevent_inline_autocomplete()) |
| 182 return true; |
| 183 #endif |
| 184 |
| 185 // The value of input.prevent_inline_autocomplete() is determined by the |
| 186 // following conditions: |
| 187 // 1. If the caret is at the end of the text. |
| 188 // 2. If it's in IME composition mode. |
| 189 // We send the caret position to Instant (so it can determine #1 itself), and |
| 190 // we use a separated widget for displaying the Instant suggest (so it doesn't |
| 191 // interfere with #2). So, we don't need to care about the value of |
| 192 // input.prevent_inline_autocomplete() here. |
| 193 return just_deleted_text || popup_->selected_line() != 0; |
| 194 } |
| 195 |
| 196 InstantController* OmniboxController::GetInstantController() const { |
| 197 return omnibox_edit_model_->GetInstantController(); |
| 198 } |
| OLD | NEW |