#include "chrome/browser/ui/omnibox/omnibox_edit_model.h"
+#include <algorithm>
#include <string>
#include "base/auto_reset.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/autocomplete/autocomplete_classifier.h"
#include "chrome/browser/autocomplete/autocomplete_classifier_factory.h"
-#include "chrome/browser/autocomplete/autocomplete_provider.h"
-#include "chrome/browser/autocomplete/extension_app_provider.h"
+#include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h"
#include "chrome/browser/autocomplete/history_url_provider.h"
-#include "chrome/browser/autocomplete/keyword_provider.h"
-#include "chrome/browser/autocomplete/search_provider.h"
+#include "chrome/browser/bookmarks/bookmark_model_factory.h"
#include "chrome/browser/bookmarks/bookmark_stats.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/command_updater.h"
#include "chrome/browser/extensions/api/omnibox/omnibox_api.h"
#include "chrome/browser/favicon/favicon_tab_helper.h"
-#include "chrome/browser/google/google_url_tracker.h"
+#include "chrome/browser/google/google_url_tracker_factory.h"
#include "chrome/browser/net/predictor.h"
#include "chrome/browser/omnibox/omnibox_log.h"
#include "chrome/browser/predictors/autocomplete_action_predictor.h"
#include "chrome/browser/prerender/prerender_manager_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search/search.h"
-#include "chrome/browser/search_engines/template_url.h"
-#include "chrome/browser/search_engines/template_url_prepopulate_data.h"
-#include "chrome/browser/search_engines/template_url_service.h"
#include "chrome/browser/search_engines/template_url_service_factory.h"
+#include "chrome/browser/search_engines/ui_thread_search_terms_data.h"
#include "chrome/browser/sessions/session_tab_helper.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/omnibox/omnibox_current_page_delegate_impl.h"
#include "chrome/browser/ui/search/search_tab_helper.h"
#include "chrome/browser/ui/toolbar/toolbar_model.h"
#include "chrome/common/chrome_switches.h"
-#include "chrome/common/net/url_fixer_upper.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
+#include "components/bookmarks/browser/bookmark_model.h"
+#include "components/google/core/browser/google_url_tracker.h"
+#include "components/metrics/proto/omnibox_event.pb.h"
+#include "components/omnibox/autocomplete_provider.h"
+#include "components/omnibox/keyword_provider.h"
+#include "components/omnibox/search_provider.h"
+#include "components/search_engines/template_url.h"
+#include "components/search_engines/template_url_prepopulate_data.h"
+#include "components/search_engines/template_url_service.h"
+#include "components/url_fixer/url_fixer.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/notification_service.h"
#include "ui/gfx/image/image.h"
#include "url/url_util.h"
+using metrics::OmniboxEventProto;
using predictors::AutocompleteActionPredictor;
void RecordPercentageMatchHistogram(const base::string16& old_text,
const base::string16& new_text,
bool url_replacement_active,
- content::PageTransition transition,
+ ui::PageTransition transition,
int omnibox_width) {
size_t avg_length = (old_text.length() + new_text.length()) / 2;
std::string histogram_name;
if (url_replacement_active) {
- if (transition == content::PAGE_TRANSITION_TYPED) {
+ if (transition == ui::PAGE_TRANSITION_TYPED) {
histogram_name = "InstantExtended.PercentageMatchV2_QuerytoURL";
UMA_HISTOGRAM_PERCENTAGE(histogram_name, percent);
} else {
UMA_HISTOGRAM_PERCENTAGE(histogram_name, percent);
}
} else {
- if (transition == content::PAGE_TRANSITION_TYPED) {
+ if (transition == ui::PAGE_TRANSITION_TYPED) {
histogram_name = "InstantExtended.PercentageMatchV2_URLtoURL";
UMA_HISTOGRAM_PERCENTAGE(histogram_name, percent);
} else {
void OmniboxEditModel::RestoreState(const State* state) {
// We need to update the permanent text correctly and revert the view
// regardless of whether there is saved state.
+ bool url_replacement_enabled = !state || state->url_replacement_enabled;
controller_->GetToolbarModel()->set_url_replacement_enabled(
- !state || state->url_replacement_enabled);
+ url_replacement_enabled);
+ controller_->GetToolbarModel()->set_origin_chip_enabled(
+ url_replacement_enabled);
permanent_text_ = controller_->GetToolbarModel()->GetText();
// Don't muck with the search term replacement state, as we've just set it
// correctly.
}
GURL OmniboxEditModel::PermanentURL() {
- return URLFixerUpper::FixupURL(base::UTF16ToUTF8(permanent_text_),
- std::string());
+ return url_fixer::FixupURL(base::UTF16ToUTF8(permanent_text_), std::string());
}
void OmniboxEditModel::SetUserText(const base::string16& text) {
// screw up our calculation of the desired_tld.
AutocompleteMatch match;
AutocompleteClassifierFactory::GetForProfile(profile_)->Classify(
- *text, KeywordIsSelected(), true, ClassifyPage(), &match, NULL);
+ *text, is_keyword_selected(), true, ClassifyPage(), &match, NULL);
if (AutocompleteMatch::IsSearchType(match.type))
return;
*url = match.destination_url;
url->SchemeIs(url::kHttpScheme) && perm_url.host() == url->host()) {
*write_url = true;
base::string16 http = base::ASCIIToUTF16(url::kHttpScheme) +
- base::ASCIIToUTF16(content::kStandardSchemeSeparator);
+ base::ASCIIToUTF16(url::kStandardSchemeSeparator);
if (text->compare(0, http.length(), http) != 0)
*text = http + *text;
}
// * For HIDE_ON_MOUSE_RELEASE, which only hides the chip on mouse release if
// the omnibox is empty, it handles the "omnibox was not empty" case by
// acting like HIDE_ON_USER_INPUT.
- if (chrome::ShouldDisplayOriginChipV2() && in_progress)
+ if (chrome::ShouldDisplayOriginChip() && in_progress)
controller()->GetToolbarModel()->set_origin_chip_enabled(false);
controller_->GetToolbarModel()->set_input_in_progress(in_progress);
+ controller_->EndOriginChipAnimations(true);
controller_->Update(NULL);
if (user_input_in_progress_ || !in_revert_)
GURL current_url =
(delegate_->CurrentPageExists() && view_->IsIndicatingQueryRefinement()) ?
delegate_->GetURL() : GURL();
- bool keyword_is_selected = KeywordIsSelected();
input_ = AutocompleteInput(
- user_text_,
- cursor_position,
- base::string16(),
- current_url,
+ user_text_, cursor_position, base::string16(), current_url,
ClassifyPage(),
prevent_inline_autocomplete || just_deleted_text_ ||
- (has_selected_text && inline_autocomplete_text_.empty()) ||
- (paste_state_ != NONE),
- keyword_is_selected,
- keyword_is_selected || allow_exact_keyword_match_,
- true);
+ (has_selected_text && inline_autocomplete_text_.empty()) ||
+ (paste_state_ != NONE),
+ is_keyword_selected(),
+ is_keyword_selected() || allow_exact_keyword_match_,
+ true, ChromeAutocompleteSchemeClassifier(profile_));
omnibox_controller_->StartAutocomplete(input_);
}
// typed. If we can successfully generate a URL_WHAT_YOU_TYPED match doing
// that, then we use this. These matches are marked as generated by the
// HistoryURLProvider so we only generate them if this provider is present.
- if (control_key_state_ == DOWN_WITHOUT_CHANGE && !KeywordIsSelected() &&
+ if (control_key_state_ == DOWN_WITHOUT_CHANGE && !is_keyword_selected() &&
autocomplete_controller()->history_url_provider()) {
// Generate a new AutocompleteInput, copying the latest one but using "com"
// as the desired TLD. Then use this autocomplete input to generate a
input_ = AutocompleteInput(
has_temporary_text_ ?
UserTextFromDisplayText(view_->GetText()) : input_.text(),
- input_.cursor_position(), base::ASCIIToUTF16("com"),
- GURL(), input_.current_page_classification(),
+ input_.cursor_position(), base::ASCIIToUTF16("com"), GURL(),
+ input_.current_page_classification(),
input_.prevent_inline_autocomplete(), input_.prefer_keyword(),
- input_.allow_exact_keyword_match(),
- input_.want_asynchronous_matches());
+ input_.allow_exact_keyword_match(), input_.want_asynchronous_matches(),
+ ChromeAutocompleteSchemeClassifier(profile_));
AutocompleteMatch url_match(
autocomplete_controller()->history_url_provider()->SuggestExactInput(
input_.text(), input_.canonicalized_url(), false));
if (!match.destination_url.is_valid())
return;
- if ((match.transition == content::PAGE_TRANSITION_TYPED) &&
+ if ((match.transition == ui::PAGE_TRANSITION_TYPED) &&
(match.destination_url == PermanentURL())) {
// When the user hit enter on the existing permanent URL, treat it like a
// reload for scoring purposes. We could detect this by just checking
// different from the current URL, even if it wound up at the same place
// (e.g. manually retyping the same search query), and it seems wrong to
// treat this as a reload.
- match.transition = content::PAGE_TRANSITION_RELOAD;
+ match.transition = ui::PAGE_TRANSITION_RELOAD;
} else if (for_drop || ((paste_state_ != NONE) &&
match.is_history_what_you_typed_match)) {
// When the user pasted in a URL and hit enter, score it like a link click
// rather than a normal typed URL, so it doesn't get inline autocompleted
// as aggressively later.
- match.transition = content::PAGE_TRANSITION_LINK;
+ match.transition = ui::PAGE_TRANSITION_LINK;
}
- const TemplateURL* template_url = match.GetTemplateURL(profile_, false);
- if (template_url && template_url->url_ref().HasGoogleBaseURLs())
- GoogleURLTracker::GoogleURLSearchCommitted(profile_);
+ TemplateURLService* service =
+ TemplateURLServiceFactory::GetForProfile(profile_);
+ const TemplateURL* template_url = match.GetTemplateURL(service, false);
+ if (template_url && template_url->url_ref().HasGoogleBaseURLs(
+ UIThreadSearchTermsData(profile_))) {
+ GoogleURLTracker* tracker =
+ GoogleURLTrackerFactory::GetForProfile(profile_);
+ if (tracker)
+ tracker->SearchCommitted();
+ }
DCHECK(popup_model());
view_->OpenMatch(match, disposition, alternate_nav_url, base::string16(),
const base::TimeTicks& now(base::TimeTicks::Now());
base::TimeDelta elapsed_time_since_user_first_modified_omnibox(
now - time_user_first_modified_omnibox_);
- autocomplete_controller()->UpdateMatchDestinationURL(
+ autocomplete_controller()->UpdateMatchDestinationURLWithQueryFormulationTime(
elapsed_time_since_user_first_modified_omnibox, &match);
base::string16 input_text(pasted_text);
base::TimeDelta elapsed_time_since_last_change_to_default_match(
now - autocomplete_controller()->last_time_default_match_changed());
+ DCHECK(match.provider);
// These elapsed times don't really make sense for ZeroSuggest matches
// (because the user does not modify the omnibox for ZeroSuggest), so for
// those we set the elapsed times to something that will be ignored by
// metrics_log.cc. They also don't necessarily make sense if the omnibox
// dropdown is closed or the user used a paste-and-go action. (In most
// cases when this happens, the user never modified the omnibox.)
- if ((match.provider &&
- (match.provider->type() == AutocompleteProvider::TYPE_ZERO_SUGGEST)) ||
+ if ((match.provider->type() == AutocompleteProvider::TYPE_ZERO_SUGGEST) ||
!popup_model()->IsOpen() || !pasted_text.empty()) {
const base::TimeDelta default_time_delta =
base::TimeDelta::FromMilliseconds(-1);
-1, // don't yet know tab ID; set later if appropriate
ClassifyPage(),
elapsed_time_since_user_first_modified_omnibox,
- match.inline_autocompletion.length(),
+ match.allowed_to_be_default_match ? match.inline_autocompletion.length() :
+ base::string16::npos,
elapsed_time_since_last_change_to_default_match,
(!popup_model()->IsOpen() || !pasted_text.empty()) ?
fake_single_entry_result : result());
chrome::NOTIFICATION_OMNIBOX_OPENED_URL,
content::Source<Profile>(profile_),
content::Details<OmniboxLog>(&log));
- HISTOGRAM_ENUMERATION("Omnibox.EventCount", 1, 2);
+ LOCAL_HISTOGRAM_BOOLEAN("Omnibox.EventCount", true);
DCHECK(!last_omnibox_focus_.is_null())
<< "An omnibox focus should have occurred before opening a match.";
UMA_HISTOGRAM_TIMES(kFocusToOpenTimeHistogram, now - last_omnibox_focus_);
- TemplateURL* template_url = match.GetTemplateURL(profile_, false);
+ TemplateURLService* service =
+ TemplateURLServiceFactory::GetForProfile(profile_);
+ TemplateURL* template_url = match.GetTemplateURL(service, false);
if (template_url) {
- if (match.transition == content::PAGE_TRANSITION_KEYWORD) {
+ if (match.transition == ui::PAGE_TRANSITION_KEYWORD) {
// The user is using a non-substituting keyword or is explicitly in
// keyword mode.
TemplateURLServiceFactory::GetForProfile(profile_)->IncrementUsageCount(
template_url);
} else {
- DCHECK_EQ(content::PAGE_TRANSITION_GENERATED, match.transition);
+ DCHECK_EQ(ui::PAGE_TRANSITION_GENERATED, match.transition);
// NOTE: We purposefully don't increment the usage count of the default
// search engine here like we do for explicit keywords above; see comments
// in template_url.h.
}
- UMA_HISTOGRAM_ENUMERATION("Omnibox.SearchEngineType",
- TemplateURLPrepopulateData::GetEngineType(*template_url),
+ UMA_HISTOGRAM_ENUMERATION(
+ "Omnibox.SearchEngineType",
+ TemplateURLPrepopulateData::GetEngineType(
+ *template_url, UIThreadSearchTermsData(profile_)),
SEARCH_ENGINE_MAX);
}
view_->RevertAll(); // Revert the box to its unedited state.
}
- if (match.type == AutocompleteMatchType::EXTENSION_APP) {
- ExtensionAppProvider::LaunchAppFromOmnibox(match, profile_, disposition);
- observer->OnSuccessfulNavigation();
- } else {
- RecordPercentageMatchHistogram(
- permanent_text_, current_text,
- controller_->GetToolbarModel()->WouldReplaceURL(),
- match.transition, view_->GetWidth());
-
- // Track whether the destination URL sends us to a search results page
- // using the default search provider.
- if (TemplateURLServiceFactory::GetForProfile(profile_)->
- IsSearchResultsPageFromDefaultSearchProvider(match.destination_url)) {
- content::RecordAction(
- base::UserMetricsAction("OmniboxDestinationURLIsSearchOnDSP"));
- }
+ RecordPercentageMatchHistogram(
+ permanent_text_, current_text,
+ controller_->GetToolbarModel()->WouldReplaceURL(),
+ match.transition, view_->GetWidth());
+
+ // Track whether the destination URL sends us to a search results page
+ // using the default search provider.
+ if (TemplateURLServiceFactory::GetForProfile(profile_)->
+ IsSearchResultsPageFromDefaultSearchProvider(match.destination_url)) {
+ content::RecordAction(
+ base::UserMetricsAction("OmniboxDestinationURLIsSearchOnDSP"));
+ }
- if (match.destination_url.is_valid()) {
- // This calls RevertAll again.
- base::AutoReset<bool> tmp(&in_revert_, true);
- controller_->OnAutocompleteAccept(
- match.destination_url, disposition,
- content::PageTransitionFromInt(
- match.transition | content::PAGE_TRANSITION_FROM_ADDRESS_BAR));
- if (observer->load_state() != OmniboxNavigationObserver::LOAD_NOT_SEEN)
- ignore_result(observer.release()); // The observer will delete itself.
- }
+ if (match.destination_url.is_valid()) {
+ // This calls RevertAll again.
+ base::AutoReset<bool> tmp(&in_revert_, true);
+ controller_->OnAutocompleteAccept(
+ match.destination_url, disposition,
+ ui::PageTransitionFromInt(
+ match.transition | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR));
+ if (observer->load_state() != OmniboxNavigationObserver::LOAD_NOT_SEEN)
+ ignore_result(observer.release()); // The observer will delete itself.
}
- if (match.starred)
+ BookmarkModel* bookmark_model = BookmarkModelFactory::GetForProfile(profile_);
+ if (bookmark_model && bookmark_model->IsBookmarked(match.destination_url))
RecordBookmarkLaunch(NULL, BOOKMARK_LAUNCH_LOCATION_OMNIBOX);
}
DisplayTextFromUserText(CurrentMatch(NULL).fill_into_edit),
save_original_selection, true);
+ view_->UpdatePlaceholderText();
+
content::RecordAction(base::UserMetricsAction("AcceptedKeywordHint"));
UMA_HISTOGRAM_ENUMERATION(kEnteredKeywordModeHistogram, entered_method,
ENTERED_KEYWORD_MODE_NUM_ITEMS);
view_->SetWindowTextAndCaretPos(window_text.c_str(), keyword_.length(),
false, true);
}
+
+ view_->UpdatePlaceholderText();
}
void OmniboxEditModel::OnSetFocus(bool control_down) {
// |permanent_text_| is empty.
autocomplete_controller()->StartZeroSuggest(AutocompleteInput(
permanent_text_, base::string16::npos, base::string16(),
- delegate_->GetURL(), ClassifyPage(), false, false, true, true));
+ delegate_->GetURL(), ClassifyPage(), false, false, true, true,
+ ChromeAutocompleteSchemeClassifier(profile_)));
}
if (user_input_in_progress_ || !in_revert_)
const base::string16& user_text =
user_input_in_progress_ ? user_text_ : permanent_text_;
- if (keyword_state_changed && KeywordIsSelected()) {
+ if (keyword_state_changed && is_keyword_selected()) {
// If we reach here, the user most likely entered keyword mode by inserting
// a space between a keyword name and a search string (as pressing space or
// tab after the keyword name alone would have been be handled in
!just_deleted_text && no_selection &&
CreatedKeywordSearchByInsertingSpaceInMiddle(old_text, user_text_,
selection_start);
+ view_->UpdatePopup();
if (allow_exact_keyword_match_) {
+ view_->UpdatePlaceholderText();
UMA_HISTOGRAM_ENUMERATION(kEnteredKeywordModeHistogram,
ENTERED_KEYWORD_MODE_VIA_SPACE_IN_MIDDLE,
ENTERED_KEYWORD_MODE_NUM_ITEMS);
+ allow_exact_keyword_match_ = false;
}
- view_->UpdatePopup();
- allow_exact_keyword_match_ = false;
// Change to keyword mode if the user is now pressing space after a keyword
// name. Note that if this is the case, then even if there was no keyword
// OnPopupDataChanged use their previous state to detect changes.
base::string16 keyword;
bool is_keyword_hint;
- match.GetKeywordUIState(profile_, &keyword, &is_keyword_hint);
+ TemplateURLService* service =
+ TemplateURLServiceFactory::GetForProfile(profile_);
+ match.GetKeywordUIState(service, &keyword, &is_keyword_hint);
if (popup_model())
popup_model()->OnResultChanged();
// OnPopupDataChanged() resets OmniboxController's |current_match_| early
view_->OnInlineAutocompleteTextCleared();
}
-bool OmniboxEditModel::KeywordIsSelected() const {
- return !is_keyword_hint_ && !keyword_.empty();
-}
-
void OmniboxEditModel::ClearPopupKeywordMode() const {
omnibox_controller_->ClearPopupKeywordMode();
}
base::string16 OmniboxEditModel::DisplayTextFromUserText(
const base::string16& text) const {
- return KeywordIsSelected() ?
+ return is_keyword_selected() ?
KeywordProvider::SplitReplacementStringFromInput(text, false) : text;
}
base::string16 OmniboxEditModel::UserTextFromDisplayText(
const base::string16& text) const {
- return KeywordIsSelected() ? (keyword_ + base::char16(' ') + text) : text;
+ return is_keyword_selected() ? (keyword_ + base::char16(' ') + text) : text;
}
void OmniboxEditModel::GetInfoForCurrentText(AutocompleteMatch* match,
// SearchProvider::CreateSearchSuggestion(), since the user may be in a
// non-default search mode such as image search.
match->type = AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED;
+ match->provider = autocomplete_controller()->search_provider();
match->destination_url =
delegate_->GetNavigationController().GetVisibleEntry()->GetURL();
- match->transition = content::PAGE_TRANSITION_RELOAD;
+ match->transition = ui::PAGE_TRANSITION_RELOAD;
} else if (query_in_progress() ||
(popup_model() && popup_model()->IsOpen())) {
if (query_in_progress()) {
*alternate_nav_url = result().alternate_nav_url();
} else {
AutocompleteClassifierFactory::GetForProfile(profile_)->Classify(
- UserTextFromDisplayText(view_->GetText()), KeywordIsSelected(), true,
+ UserTextFromDisplayText(view_->GetText()), is_keyword_selected(), true,
ClassifyPage(), match, alternate_nav_url);
}
}
}
}
-AutocompleteInput::PageClassification OmniboxEditModel::ClassifyPage() const {
+OmniboxEventProto::PageClassification OmniboxEditModel::ClassifyPage() const {
if (!delegate_->CurrentPageExists())
- return AutocompleteInput::OTHER;
+ return OmniboxEventProto::OTHER;
if (delegate_->IsInstantNTP()) {
// Note that we treat OMNIBOX as the source if focus_source_ is INVALID,
// i.e., if input isn't actually in progress.
return (focus_source_ == FAKEBOX) ?
- AutocompleteInput::INSTANT_NTP_WITH_FAKEBOX_AS_STARTING_FOCUS :
- AutocompleteInput::INSTANT_NTP_WITH_OMNIBOX_AS_STARTING_FOCUS;
+ OmniboxEventProto::INSTANT_NTP_WITH_FAKEBOX_AS_STARTING_FOCUS :
+ OmniboxEventProto::INSTANT_NTP_WITH_OMNIBOX_AS_STARTING_FOCUS;
}
const GURL& gurl = delegate_->GetURL();
if (!gurl.is_valid())
- return AutocompleteInput::INVALID_SPEC;
+ return OmniboxEventProto::INVALID_SPEC;
const std::string& url = gurl.spec();
if (url == chrome::kChromeUINewTabURL)
- return AutocompleteInput::NTP;
- if (url == content::kAboutBlankURL)
- return AutocompleteInput::BLANK;
+ return OmniboxEventProto::NTP;
+ if (url == url::kAboutBlankURL)
+ return OmniboxEventProto::BLANK;
if (url == profile()->GetPrefs()->GetString(prefs::kHomePage))
- return AutocompleteInput::HOME_PAGE;
+ return OmniboxEventProto::HOME_PAGE;
if (controller_->GetToolbarModel()->WouldPerformSearchTermReplacement(true))
- return AutocompleteInput::SEARCH_RESULT_PAGE_DOING_SEARCH_TERM_REPLACEMENT;
+ return OmniboxEventProto::SEARCH_RESULT_PAGE_DOING_SEARCH_TERM_REPLACEMENT;
if (delegate_->IsSearchResultsPage())
- return AutocompleteInput::SEARCH_RESULT_PAGE_NO_SEARCH_TERM_REPLACEMENT;
- return AutocompleteInput::OTHER;
+ return OmniboxEventProto::SEARCH_RESULT_PAGE_NO_SEARCH_TERM_REPLACEMENT;
+ return OmniboxEventProto::OTHER;
}
void OmniboxEditModel::ClassifyStringForPasteAndGo(