OLD | NEW |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 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 "components/omnibox/browser/omnibox_edit_model.h" | 5 #include "components/omnibox/browser/omnibox_edit_model.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <string> | 8 #include <string> |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
82 // between focusing and opening an omnibox match. | 82 // between focusing and opening an omnibox match. |
83 const char kFocusToOpenTimeHistogram[] = | 83 const char kFocusToOpenTimeHistogram[] = |
84 "Omnibox.FocusToOpenTimeAnyPopupState2"; | 84 "Omnibox.FocusToOpenTimeAnyPopupState2"; |
85 | 85 |
86 // Split the percentage match histograms into buckets based on the width of the | 86 // Split the percentage match histograms into buckets based on the width of the |
87 // omnibox. | 87 // omnibox. |
88 const int kPercentageMatchHistogramWidthBuckets[] = { 400, 700, 1200 }; | 88 const int kPercentageMatchHistogramWidthBuckets[] = { 400, 700, 1200 }; |
89 | 89 |
90 void RecordPercentageMatchHistogram(const base::string16& old_text, | 90 void RecordPercentageMatchHistogram(const base::string16& old_text, |
91 const base::string16& new_text, | 91 const base::string16& new_text, |
92 bool url_replacement_active, | |
93 ui::PageTransition transition, | 92 ui::PageTransition transition, |
94 int omnibox_width) { | 93 int omnibox_width) { |
95 size_t avg_length = (old_text.length() + new_text.length()) / 2; | 94 size_t avg_length = (old_text.length() + new_text.length()) / 2; |
96 | 95 |
97 int percent = 0; | 96 int percent = 0; |
98 if (!old_text.empty() && !new_text.empty()) { | 97 if (!old_text.empty() && !new_text.empty()) { |
99 size_t shorter_length = std::min(old_text.length(), new_text.length()); | 98 size_t shorter_length = std::min(old_text.length(), new_text.length()); |
100 base::string16::const_iterator end(old_text.begin() + shorter_length); | 99 base::string16::const_iterator end(old_text.begin() + shorter_length); |
101 base::string16::const_iterator mismatch( | 100 base::string16::const_iterator mismatch( |
102 std::mismatch(old_text.begin(), end, new_text.begin()).first); | 101 std::mismatch(old_text.begin(), end, new_text.begin()).first); |
103 size_t matching_characters = mismatch - old_text.begin(); | 102 size_t matching_characters = mismatch - old_text.begin(); |
104 percent = static_cast<float>(matching_characters) / avg_length * 100; | 103 percent = static_cast<float>(matching_characters) / avg_length * 100; |
105 } | 104 } |
106 | 105 |
| 106 // TODO(treib,mpearson): Do we want to keep these histograms? Most of the |
| 107 // previously-logged cases don't exist anymore. crbug.com/627747 |
107 std::string histogram_name; | 108 std::string histogram_name; |
108 if (url_replacement_active) { | 109 if (ui::PageTransitionTypeIncludingQualifiersIs( |
109 if (ui::PageTransitionTypeIncludingQualifiersIs( | 110 transition, ui::PAGE_TRANSITION_TYPED)) { |
110 transition, ui::PAGE_TRANSITION_TYPED)) { | 111 histogram_name = "InstantExtended.PercentageMatchV2_URLtoURL"; |
111 histogram_name = "InstantExtended.PercentageMatchV2_QuerytoURL"; | 112 UMA_HISTOGRAM_PERCENTAGE(histogram_name, percent); |
112 UMA_HISTOGRAM_PERCENTAGE(histogram_name, percent); | |
113 } else { | |
114 histogram_name = "InstantExtended.PercentageMatchV2_QuerytoQuery"; | |
115 UMA_HISTOGRAM_PERCENTAGE(histogram_name, percent); | |
116 } | |
117 } else { | 113 } else { |
118 if (ui::PageTransitionTypeIncludingQualifiersIs( | 114 histogram_name = "InstantExtended.PercentageMatchV2_URLtoQuery"; |
119 transition, ui::PAGE_TRANSITION_TYPED)) { | 115 UMA_HISTOGRAM_PERCENTAGE(histogram_name, percent); |
120 histogram_name = "InstantExtended.PercentageMatchV2_URLtoURL"; | |
121 UMA_HISTOGRAM_PERCENTAGE(histogram_name, percent); | |
122 } else { | |
123 histogram_name = "InstantExtended.PercentageMatchV2_URLtoQuery"; | |
124 UMA_HISTOGRAM_PERCENTAGE(histogram_name, percent); | |
125 } | |
126 } | 116 } |
127 | 117 |
128 std::string suffix = "large"; | 118 std::string suffix = "large"; |
129 for (size_t i = 0; i < arraysize(kPercentageMatchHistogramWidthBuckets); | 119 for (size_t i = 0; i < arraysize(kPercentageMatchHistogramWidthBuckets); |
130 ++i) { | 120 ++i) { |
131 if (omnibox_width < kPercentageMatchHistogramWidthBuckets[i]) { | 121 if (omnibox_width < kPercentageMatchHistogramWidthBuckets[i]) { |
132 suffix = base::IntToString(kPercentageMatchHistogramWidthBuckets[i]); | 122 suffix = base::IntToString(kPercentageMatchHistogramWidthBuckets[i]); |
133 break; | 123 break; |
134 } | 124 } |
135 } | 125 } |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
226 controller_->GetToolbarModel()->url_replacement_enabled(), | 216 controller_->GetToolbarModel()->url_replacement_enabled(), |
227 focus_state_, focus_source_, input_); | 217 focus_state_, focus_source_, input_); |
228 } | 218 } |
229 | 219 |
230 void OmniboxEditModel::RestoreState(const State* state) { | 220 void OmniboxEditModel::RestoreState(const State* state) { |
231 // We need to update the permanent text correctly and revert the view | 221 // We need to update the permanent text correctly and revert the view |
232 // regardless of whether there is saved state. | 222 // regardless of whether there is saved state. |
233 bool url_replacement_enabled = !state || state->url_replacement_enabled; | 223 bool url_replacement_enabled = !state || state->url_replacement_enabled; |
234 controller_->GetToolbarModel()->set_url_replacement_enabled( | 224 controller_->GetToolbarModel()->set_url_replacement_enabled( |
235 url_replacement_enabled); | 225 url_replacement_enabled); |
236 permanent_text_ = controller_->GetToolbarModel()->GetText(); | 226 permanent_text_ = controller_->GetToolbarModel()->GetFormattedURL(nullptr); |
237 // Don't muck with the search term replacement state, as we've just set it | 227 // Don't muck with the search term replacement state, as we've just set it |
238 // correctly. | 228 // correctly. |
239 view_->RevertWithoutResettingSearchTermReplacement(); | 229 view_->RevertWithoutResettingSearchTermReplacement(); |
240 // Restore the autocomplete controller's input, or clear it if this is a new | 230 // Restore the autocomplete controller's input, or clear it if this is a new |
241 // tab. | 231 // tab. |
242 input_ = state ? state->autocomplete_input : AutocompleteInput(); | 232 input_ = state ? state->autocomplete_input : AutocompleteInput(); |
243 if (!state) | 233 if (!state) |
244 return; | 234 return; |
245 | 235 |
246 SetFocusState(state->focus_state, OMNIBOX_FOCUS_CHANGE_TAB_SWITCH); | 236 SetFocusState(state->focus_state, OMNIBOX_FOCUS_CHANGE_TAB_SWITCH); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
284 // always safe to change the text; this also prevents someone toggling "Show | 274 // always safe to change the text; this also prevents someone toggling "Show |
285 // URL" (which sounds as if it might be persistent) from seeing just that URL | 275 // URL" (which sounds as if it might be persistent) from seeing just that URL |
286 // forever afterwards. | 276 // forever afterwards. |
287 // | 277 // |
288 // If the page is auto-committing gray text, however, we generally don't want | 278 // If the page is auto-committing gray text, however, we generally don't want |
289 // to make any change to the edit. While auto-commits modify the underlying | 279 // to make any change to the edit. While auto-commits modify the underlying |
290 // permanent URL, they're intended to have no effect on the user's editing | 280 // permanent URL, they're intended to have no effect on the user's editing |
291 // process -- before and after the auto-commit, the omnibox should show the | 281 // process -- before and after the auto-commit, the omnibox should show the |
292 // same user text and the same instant suggestion, even if the auto-commit | 282 // same user text and the same instant suggestion, even if the auto-commit |
293 // happens while the edit doesn't have focus. | 283 // happens while the edit doesn't have focus. |
294 base::string16 new_permanent_text = controller_->GetToolbarModel()->GetText(); | 284 base::string16 new_permanent_text = |
| 285 controller_->GetToolbarModel()->GetFormattedURL(nullptr); |
295 base::string16 gray_text = view_->GetGrayTextAutocompletion(); | 286 base::string16 gray_text = view_->GetGrayTextAutocompletion(); |
296 const bool visibly_changed_permanent_text = | 287 const bool visibly_changed_permanent_text = |
297 (permanent_text_ != new_permanent_text) && | 288 (permanent_text_ != new_permanent_text) && |
298 (!has_focus() || | 289 (!has_focus() || |
299 (!user_input_in_progress_ && !PopupIsOpen() && | 290 (!user_input_in_progress_ && !PopupIsOpen() && |
300 controller_->GetToolbarModel()->url_replacement_enabled())) && | 291 controller_->GetToolbarModel()->url_replacement_enabled())) && |
301 (gray_text.empty() || | 292 (gray_text.empty() || |
302 new_permanent_text != user_text_ + gray_text); | 293 new_permanent_text != user_text_ + gray_text); |
303 | 294 |
304 permanent_text_ = new_permanent_text; | 295 permanent_text_ = new_permanent_text; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
352 base::string16* title, | 343 base::string16* title, |
353 gfx::Image* favicon) { | 344 gfx::Image* favicon) { |
354 *url = CurrentMatch(nullptr).destination_url; | 345 *url = CurrentMatch(nullptr).destination_url; |
355 if (*url == client_->GetURL()) { | 346 if (*url == client_->GetURL()) { |
356 *title = client_->GetTitle(); | 347 *title = client_->GetTitle(); |
357 *favicon = client_->GetFavicon(); | 348 *favicon = client_->GetFavicon(); |
358 } | 349 } |
359 } | 350 } |
360 | 351 |
361 bool OmniboxEditModel::CurrentTextIsURL() const { | 352 bool OmniboxEditModel::CurrentTextIsURL() const { |
362 if (controller_->GetToolbarModel()->WouldReplaceURL()) | 353 // If !user_input_in_progress_, then permanent text is showing and should be a |
363 return false; | |
364 | |
365 // If current text is not composed of replaced search terms and | |
366 // !user_input_in_progress_, then permanent text is showing and should be a | |
367 // URL, so no further checking is needed. By avoiding checking in this case, | 354 // URL, so no further checking is needed. By avoiding checking in this case, |
368 // we avoid calling into the autocomplete providers, and thus initializing the | 355 // we avoid calling into the autocomplete providers, and thus initializing the |
369 // history system, as long as possible, which speeds startup. | 356 // history system, as long as possible, which speeds startup. |
370 if (!user_input_in_progress_) | 357 if (!user_input_in_progress_) |
371 return true; | 358 return true; |
372 | 359 |
373 return !AutocompleteMatch::IsSearchType(CurrentMatch(nullptr).type); | 360 return !AutocompleteMatch::IsSearchType(CurrentMatch(nullptr).type); |
374 } | 361 } |
375 | 362 |
376 AutocompleteMatch::Type OmniboxEditModel::CurrentTextType() const { | 363 AutocompleteMatch::Type OmniboxEditModel::CurrentTextType() const { |
377 return CurrentMatch(nullptr).type; | 364 return CurrentMatch(nullptr).type; |
378 } | 365 } |
379 | 366 |
380 void OmniboxEditModel::AdjustTextForCopy(int sel_min, | 367 void OmniboxEditModel::AdjustTextForCopy(int sel_min, |
381 bool is_all_selected, | 368 bool is_all_selected, |
382 base::string16* text, | 369 base::string16* text, |
383 GURL* url, | 370 GURL* url, |
384 bool* write_url) { | 371 bool* write_url) { |
385 *write_url = false; | 372 *write_url = false; |
386 | 373 |
387 // Do not adjust if selection did not start at the beginning of the field, or | 374 // Do not adjust if selection did not start at the beginning of the field. |
388 // if the URL was omitted. | 375 if (sel_min != 0) |
389 if ((sel_min != 0) || controller_->GetToolbarModel()->WouldReplaceURL()) | |
390 return; | 376 return; |
391 | 377 |
392 // Check whether the user is trying to copy the current page's URL by | 378 // Check whether the user is trying to copy the current page's URL by |
393 // selecting the whole thing without editing it. | 379 // selecting the whole thing without editing it. |
394 // | 380 // |
395 // This is complicated by ZeroSuggest. When ZeroSuggest is active, the user | 381 // This is complicated by ZeroSuggest. When ZeroSuggest is active, the user |
396 // may be selecting different items and thus changing the address bar text, | 382 // may be selecting different items and thus changing the address bar text, |
397 // even though !user_input_in_progress_; and the permanent URL may change | 383 // even though !user_input_in_progress_; and the permanent URL may change |
398 // without updating the visible text, just like when user input is in | 384 // without updating the visible text, just like when user input is in |
399 // progress. In these cases, we don't want to copy the underlying URL, we | 385 // progress. In these cases, we don't want to copy the underlying URL, we |
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
773 | 759 |
774 // Get the current text before we call RevertAll() which will clear it. | 760 // Get the current text before we call RevertAll() which will clear it. |
775 base::string16 current_text = view_->GetText(); | 761 base::string16 current_text = view_->GetText(); |
776 | 762 |
777 if (disposition != NEW_BACKGROUND_TAB) { | 763 if (disposition != NEW_BACKGROUND_TAB) { |
778 base::AutoReset<bool> tmp(&in_revert_, true); | 764 base::AutoReset<bool> tmp(&in_revert_, true); |
779 view_->RevertAll(); // Revert the box to its unedited state. | 765 view_->RevertAll(); // Revert the box to its unedited state. |
780 } | 766 } |
781 | 767 |
782 RecordPercentageMatchHistogram( | 768 RecordPercentageMatchHistogram( |
783 permanent_text_, current_text, | 769 permanent_text_, current_text, match.transition, view_->GetWidth()); |
784 controller_->GetToolbarModel()->WouldReplaceURL(), | |
785 match.transition, view_->GetWidth()); | |
786 | 770 |
787 // Track whether the destination URL sends us to a search results page | 771 // Track whether the destination URL sends us to a search results page |
788 // using the default search provider. | 772 // using the default search provider. |
789 TemplateURLService* template_url_service = client_->GetTemplateURLService(); | 773 TemplateURLService* template_url_service = client_->GetTemplateURLService(); |
790 if (template_url_service && | 774 if (template_url_service && |
791 template_url_service->IsSearchResultsPageFromDefaultSearchProvider( | 775 template_url_service->IsSearchResultsPageFromDefaultSearchProvider( |
792 match.destination_url)) { | 776 match.destination_url)) { |
793 base::RecordAction( | 777 base::RecordAction( |
794 base::UserMetricsAction("OmniboxDestinationURLIsSearchOnDSP")); | 778 base::UserMetricsAction("OmniboxDestinationURLIsSearchOnDSP")); |
795 } | 779 } |
(...skipping 581 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1377 | 1361 |
1378 base::string16 OmniboxEditModel::MaybePrependKeyword( | 1362 base::string16 OmniboxEditModel::MaybePrependKeyword( |
1379 const base::string16& text) const { | 1363 const base::string16& text) const { |
1380 return is_keyword_selected() ? (keyword_ + base::char16(' ') + text) : text; | 1364 return is_keyword_selected() ? (keyword_ + base::char16(' ') + text) : text; |
1381 } | 1365 } |
1382 | 1366 |
1383 void OmniboxEditModel::GetInfoForCurrentText(AutocompleteMatch* match, | 1367 void OmniboxEditModel::GetInfoForCurrentText(AutocompleteMatch* match, |
1384 GURL* alternate_nav_url) const { | 1368 GURL* alternate_nav_url) const { |
1385 DCHECK(match); | 1369 DCHECK(match); |
1386 | 1370 |
1387 if (controller_->GetToolbarModel()->WouldPerformSearchTermReplacement( | 1371 if (query_in_progress() || PopupIsOpen()) { |
1388 false)) { | |
1389 // Any time the user hits enter on the unchanged omnibox, we should reload. | |
1390 // When we're not extracting search terms, AcceptInput() will take care of | |
1391 // this (see code referring to PAGE_TRANSITION_RELOAD there), but when we're | |
1392 // extracting search terms, the conditionals there won't fire, so we | |
1393 // explicitly set up a match that will reload here. | |
1394 | |
1395 // It's important that we fetch the current visible URL to reload instead of | |
1396 // just getting a "search what you typed" URL from | |
1397 // SearchProvider::CreateSearchSuggestion(), since the user may be in a | |
1398 // non-default search mode such as image search. | |
1399 match->type = AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED; | |
1400 match->provider = autocomplete_controller()->search_provider(); | |
1401 match->destination_url = client_->GetURL(); | |
1402 match->transition = ui::PAGE_TRANSITION_RELOAD; | |
1403 } else if (query_in_progress() || PopupIsOpen()) { | |
1404 if (query_in_progress()) { | 1372 if (query_in_progress()) { |
1405 // It's technically possible for |result| to be empty if no provider | 1373 // It's technically possible for |result| to be empty if no provider |
1406 // returns a synchronous result but the query has not completed | 1374 // returns a synchronous result but the query has not completed |
1407 // synchronously; pratically, however, that should never actually happen. | 1375 // synchronously; pratically, however, that should never actually happen. |
1408 if (result().empty()) | 1376 if (result().empty()) |
1409 return; | 1377 return; |
1410 // The user cannot have manually selected a match, or the query would have | 1378 // The user cannot have manually selected a match, or the query would have |
1411 // stopped. So the default match must be the desired selection. | 1379 // stopped. So the default match must be the desired selection. |
1412 *match = *result().default_match(); | 1380 *match = *result().default_match(); |
1413 } else { | 1381 } else { |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1505 const GURL& gurl = client_->GetURL(); | 1473 const GURL& gurl = client_->GetURL(); |
1506 if (!gurl.is_valid()) | 1474 if (!gurl.is_valid()) |
1507 return OmniboxEventProto::INVALID_SPEC; | 1475 return OmniboxEventProto::INVALID_SPEC; |
1508 const std::string& url = gurl.spec(); | 1476 const std::string& url = gurl.spec(); |
1509 if (client_->IsNewTabPage(url)) | 1477 if (client_->IsNewTabPage(url)) |
1510 return OmniboxEventProto::NTP; | 1478 return OmniboxEventProto::NTP; |
1511 if (url == url::kAboutBlankURL) | 1479 if (url == url::kAboutBlankURL) |
1512 return OmniboxEventProto::BLANK; | 1480 return OmniboxEventProto::BLANK; |
1513 if (client_->IsHomePage(url)) | 1481 if (client_->IsHomePage(url)) |
1514 return OmniboxEventProto::HOME_PAGE; | 1482 return OmniboxEventProto::HOME_PAGE; |
1515 if (controller_->GetToolbarModel()->WouldPerformSearchTermReplacement(true)) | |
1516 return OmniboxEventProto::SEARCH_RESULT_PAGE_DOING_SEARCH_TERM_REPLACEMENT; | |
1517 if (client_->IsSearchResultsPage()) | 1483 if (client_->IsSearchResultsPage()) |
1518 return OmniboxEventProto::SEARCH_RESULT_PAGE_NO_SEARCH_TERM_REPLACEMENT; | 1484 return OmniboxEventProto::SEARCH_RESULT_PAGE_NO_SEARCH_TERM_REPLACEMENT; |
1519 return OmniboxEventProto::OTHER; | 1485 return OmniboxEventProto::OTHER; |
1520 } | 1486 } |
1521 | 1487 |
1522 void OmniboxEditModel::ClassifyStringForPasteAndGo( | 1488 void OmniboxEditModel::ClassifyStringForPasteAndGo( |
1523 const base::string16& text, | 1489 const base::string16& text, |
1524 AutocompleteMatch* match, | 1490 AutocompleteMatch* match, |
1525 GURL* alternate_nav_url) const { | 1491 GURL* alternate_nav_url) const { |
1526 DCHECK(match); | 1492 DCHECK(match); |
1527 client_->GetAutocompleteClassifier()->Classify( | 1493 client_->GetAutocompleteClassifier()->Classify( |
1528 text, false, false, ClassifyPage(), match, alternate_nav_url); | 1494 text, false, false, ClassifyPage(), match, alternate_nav_url); |
1529 } | 1495 } |
1530 | 1496 |
1531 void OmniboxEditModel::SetFocusState(OmniboxFocusState state, | 1497 void OmniboxEditModel::SetFocusState(OmniboxFocusState state, |
1532 OmniboxFocusChangeReason reason) { | 1498 OmniboxFocusChangeReason reason) { |
1533 if (state == focus_state_) | 1499 if (state == focus_state_) |
1534 return; | 1500 return; |
1535 | 1501 |
1536 // Update state and notify view if the omnibox has focus and the caret | 1502 // Update state and notify view if the omnibox has focus and the caret |
1537 // visibility changed. | 1503 // visibility changed. |
1538 const bool was_caret_visible = is_caret_visible(); | 1504 const bool was_caret_visible = is_caret_visible(); |
1539 focus_state_ = state; | 1505 focus_state_ = state; |
1540 if (focus_state_ != OMNIBOX_FOCUS_NONE && | 1506 if (focus_state_ != OMNIBOX_FOCUS_NONE && |
1541 is_caret_visible() != was_caret_visible) | 1507 is_caret_visible() != was_caret_visible) |
1542 view_->ApplyCaretVisibility(); | 1508 view_->ApplyCaretVisibility(); |
1543 | 1509 |
1544 client_->OnFocusChanged(focus_state_, reason); | 1510 client_->OnFocusChanged(focus_state_, reason); |
1545 } | 1511 } |
OLD | NEW |