Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(77)

Side by Side Diff: chrome/browser/autocomplete/autocomplete.cc

Issue 10699032: autocomplete: Extract AutocompleteResult from autocomplete.*. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: move comments Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 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 "chrome/browser/autocomplete/autocomplete.h" 5 #include "chrome/browser/autocomplete/autocomplete.h"
6 6
7 #include <algorithm>
8 #include <iterator>
9
10 #include "base/string_util.h" 7 #include "base/string_util.h"
11 #include "base/utf_string_conversions.h" 8 #include "base/utf_string_conversions.h"
12 #include "chrome/browser/autocomplete/autocomplete_controller_delegate.h"
13 #include "chrome/browser/autocomplete/autocomplete_match.h"
14 #include "chrome/browser/extensions/extension_service.h"
15 #include "chrome/browser/external_protocol/external_protocol_handler.h" 9 #include "chrome/browser/external_protocol/external_protocol_handler.h"
16 #include "chrome/browser/net/url_fixer_upper.h" 10 #include "chrome/browser/net/url_fixer_upper.h"
17 #include "chrome/browser/profiles/profile_io_data.h" 11 #include "chrome/browser/profiles/profile_io_data.h"
18 #include "chrome/common/url_constants.h" 12 #include "content/public/common/url_constants.h"
19 #include "googleurl/src/gurl.h"
20 #include "googleurl/src/url_canon_ip.h" 13 #include "googleurl/src/url_canon_ip.h"
21 #include "net/base/net_util.h" 14 #include "net/base/net_util.h"
22 #include "net/base/registry_controlled_domain.h" 15 #include "net/base/registry_controlled_domain.h"
23 16
24
25 // AutocompleteInput ----------------------------------------------------------
26
27 AutocompleteInput::AutocompleteInput() 17 AutocompleteInput::AutocompleteInput()
28 : type_(INVALID), 18 : type_(INVALID),
29 prevent_inline_autocomplete_(false), 19 prevent_inline_autocomplete_(false),
30 prefer_keyword_(false), 20 prefer_keyword_(false),
31 allow_exact_keyword_match_(true), 21 allow_exact_keyword_match_(true),
32 matches_requested_(ALL_MATCHES) { 22 matches_requested_(ALL_MATCHES) {
33 } 23 }
34 24
35 AutocompleteInput::AutocompleteInput(const string16& text, 25 AutocompleteInput::AutocompleteInput(const string16& text,
36 const string16& desired_tld, 26 const string16& desired_tld,
(...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after
483 473
484 void AutocompleteInput::Clear() { 474 void AutocompleteInput::Clear() {
485 text_.clear(); 475 text_.clear();
486 type_ = INVALID; 476 type_ = INVALID;
487 parts_ = url_parse::Parsed(); 477 parts_ = url_parse::Parsed();
488 scheme_.clear(); 478 scheme_.clear();
489 desired_tld_.clear(); 479 desired_tld_.clear();
490 prevent_inline_autocomplete_ = false; 480 prevent_inline_autocomplete_ = false;
491 prefer_keyword_ = false; 481 prefer_keyword_ = false;
492 } 482 }
493
494 // AutocompleteResult ---------------------------------------------------------
495
496 // static
497 const size_t AutocompleteResult::kMaxMatches = 6;
498 const int AutocompleteResult::kLowestDefaultScore = 1200;
499
500 void AutocompleteResult::Selection::Clear() {
501 destination_url = GURL();
502 provider_affinity = NULL;
503 is_history_what_you_typed_match = false;
504 }
505
506 AutocompleteResult::AutocompleteResult() {
507 // Reserve space for the max number of matches we'll show.
508 matches_.reserve(kMaxMatches);
509
510 // It's probably safe to do this in the initializer list, but there's little
511 // penalty to doing it here and it ensures our object is fully constructed
512 // before calling member functions.
513 default_match_ = end();
514 }
515
516 AutocompleteResult::~AutocompleteResult() {}
517
518 void AutocompleteResult::CopyFrom(const AutocompleteResult& rhs) {
519 if (this == &rhs)
520 return;
521
522 matches_ = rhs.matches_;
523 // Careful! You can't just copy iterators from another container, you have to
524 // reconstruct them.
525 default_match_ = (rhs.default_match_ == rhs.end()) ?
526 end() : (begin() + (rhs.default_match_ - rhs.begin()));
527
528 alternate_nav_url_ = rhs.alternate_nav_url_;
529 }
530
531 void AutocompleteResult::CopyOldMatches(const AutocompleteInput& input,
532 const AutocompleteResult& old_matches) {
533 if (old_matches.empty())
534 return;
535
536 if (empty()) {
537 // If we've got no matches we can copy everything from the last result.
538 CopyFrom(old_matches);
539 for (ACMatches::iterator i = begin(); i != end(); ++i)
540 i->from_previous = true;
541 return;
542 }
543
544 // In hopes of providing a stable popup we try to keep the number of matches
545 // per provider consistent. Other schemes (such as blindly copying the most
546 // relevant matches) typically result in many successive 'What You Typed'
547 // results filling all the matches, which looks awful.
548 //
549 // Instead of starting with the current matches and then adding old matches
550 // until we hit our overall limit, we copy enough old matches so that each
551 // provider has at least as many as before, and then use SortAndCull() to
552 // clamp globally. This way, old high-relevance matches will starve new
553 // low-relevance matches, under the assumption that the new matches will
554 // ultimately be similar. If the assumption holds, this prevents seeing the
555 // new low-relevance match appear and then quickly get pushed off the bottom;
556 // if it doesn't, then once the providers are done and we expire the old
557 // matches, the new ones will all become visible, so we won't have lost
558 // anything permanently.
559 ProviderToMatches matches_per_provider, old_matches_per_provider;
560 BuildProviderToMatches(&matches_per_provider);
561 old_matches.BuildProviderToMatches(&old_matches_per_provider);
562 for (ProviderToMatches::const_iterator i = old_matches_per_provider.begin();
563 i != old_matches_per_provider.end(); ++i) {
564 MergeMatchesByProvider(i->second, matches_per_provider[i->first]);
565 }
566
567 SortAndCull(input);
568 }
569
570 void AutocompleteResult::AppendMatches(const ACMatches& matches) {
571 #ifndef NDEBUG
572 for (ACMatches::const_iterator i = matches.begin(); i != matches.end(); ++i) {
573 DCHECK_EQ(AutocompleteMatch::SanitizeString(i->contents), i->contents);
574 DCHECK_EQ(AutocompleteMatch::SanitizeString(i->description),
575 i->description);
576 }
577 #endif
578 std::copy(matches.begin(), matches.end(), std::back_inserter(matches_));
579 default_match_ = end();
580 alternate_nav_url_ = GURL();
581 }
582
583 void AutocompleteResult::AddMatch(const AutocompleteMatch& match) {
584 DCHECK(default_match_ != end());
585 DCHECK_EQ(AutocompleteMatch::SanitizeString(match.contents), match.contents);
586 DCHECK_EQ(AutocompleteMatch::SanitizeString(match.description),
587 match.description);
588 ACMatches::iterator insertion_point =
589 std::upper_bound(begin(), end(), match, &AutocompleteMatch::MoreRelevant);
590 matches_difference_type default_offset = default_match_ - begin();
591 if ((insertion_point - begin()) <= default_offset)
592 ++default_offset;
593 matches_.insert(insertion_point, match);
594 default_match_ = begin() + default_offset;
595 }
596
597 void AutocompleteResult::SortAndCull(const AutocompleteInput& input) {
598 for (ACMatches::iterator i = matches_.begin(); i != matches_.end(); ++i)
599 i->ComputeStrippedDestinationURL();
600
601 // Remove duplicates.
602 std::sort(matches_.begin(), matches_.end(),
603 &AutocompleteMatch::DestinationSortFunc);
604 matches_.erase(std::unique(matches_.begin(), matches_.end(),
605 &AutocompleteMatch::DestinationsEqual),
606 matches_.end());
607
608 // Sort and trim to the most relevant kMaxMatches matches.
609 const size_t num_matches = std::min(kMaxMatches, matches_.size());
610 std::partial_sort(matches_.begin(), matches_.begin() + num_matches,
611 matches_.end(), &AutocompleteMatch::MoreRelevant);
612 matches_.resize(num_matches);
613
614 default_match_ = begin();
615
616 // Set the alternate nav URL.
617 alternate_nav_url_ = GURL();
618 if (((input.type() == AutocompleteInput::UNKNOWN) ||
619 (input.type() == AutocompleteInput::REQUESTED_URL)) &&
620 (default_match_ != end()) &&
621 (default_match_->transition != content::PAGE_TRANSITION_TYPED) &&
622 (default_match_->transition != content::PAGE_TRANSITION_KEYWORD) &&
623 (input.canonicalized_url() != default_match_->destination_url))
624 alternate_nav_url_ = input.canonicalized_url();
625 }
626
627 bool AutocompleteResult::HasCopiedMatches() const {
628 for (ACMatches::const_iterator i = begin(); i != end(); ++i) {
629 if (i->from_previous)
630 return true;
631 }
632 return false;
633 }
634
635 size_t AutocompleteResult::size() const {
636 return matches_.size();
637 }
638
639 bool AutocompleteResult::empty() const {
640 return matches_.empty();
641 }
642
643 AutocompleteResult::const_iterator AutocompleteResult::begin() const {
644 return matches_.begin();
645 }
646
647 AutocompleteResult::iterator AutocompleteResult::begin() {
648 return matches_.begin();
649 }
650
651 AutocompleteResult::const_iterator AutocompleteResult::end() const {
652 return matches_.end();
653 }
654
655 AutocompleteResult::iterator AutocompleteResult::end() {
656 return matches_.end();
657 }
658
659 // Returns the match at the given index.
660 const AutocompleteMatch& AutocompleteResult::match_at(size_t index) const {
661 DCHECK_LT(index, matches_.size());
662 return matches_[index];
663 }
664
665 AutocompleteMatch* AutocompleteResult::match_at(size_t index) {
666 DCHECK_LT(index, matches_.size());
667 return &matches_[index];
668 }
669
670 void AutocompleteResult::Reset() {
671 matches_.clear();
672 default_match_ = end();
673 }
674
675 void AutocompleteResult::Swap(AutocompleteResult* other) {
676 const size_t default_match_offset = default_match_ - begin();
677 const size_t other_default_match_offset =
678 other->default_match_ - other->begin();
679 matches_.swap(other->matches_);
680 default_match_ = begin() + other_default_match_offset;
681 other->default_match_ = other->begin() + default_match_offset;
682 alternate_nav_url_.Swap(&(other->alternate_nav_url_));
683 }
684
685 #ifndef NDEBUG
686 void AutocompleteResult::Validate() const {
687 for (const_iterator i(begin()); i != end(); ++i)
688 i->Validate();
689 }
690 #endif
691
692 void AutocompleteResult::BuildProviderToMatches(
693 ProviderToMatches* provider_to_matches) const {
694 for (ACMatches::const_iterator i = begin(); i != end(); ++i)
695 (*provider_to_matches)[i->provider].push_back(*i);
696 }
697
698 // static
699 bool AutocompleteResult::HasMatchByDestination(const AutocompleteMatch& match,
700 const ACMatches& matches) {
701 for (ACMatches::const_iterator i = matches.begin(); i != matches.end(); ++i) {
702 if (i->destination_url == match.destination_url)
703 return true;
704 }
705 return false;
706 }
707
708 void AutocompleteResult::MergeMatchesByProvider(const ACMatches& old_matches,
709 const ACMatches& new_matches) {
710 if (new_matches.size() >= old_matches.size())
711 return;
712
713 size_t delta = old_matches.size() - new_matches.size();
714 const int max_relevance = (new_matches.empty() ?
715 matches_.front().relevance : new_matches[0].relevance) - 1;
716 // Because the goal is a visibly-stable popup, rather than one that preserves
717 // the highest-relevance matches, we copy in the lowest-relevance matches
718 // first. This means that within each provider's "group" of matches, any
719 // synchronous matches (which tend to have the highest scores) will
720 // "overwrite" the initial matches from that provider's previous results,
721 // minimally disturbing the rest of the matches.
722 for (ACMatches::const_reverse_iterator i = old_matches.rbegin();
723 i != old_matches.rend() && delta > 0; ++i) {
724 if (!HasMatchByDestination(*i, new_matches)) {
725 AutocompleteMatch match = *i;
726 match.relevance = std::min(max_relevance, match.relevance);
727 match.from_previous = true;
728 AddMatch(match);
729 delta--;
730 }
731 }
732 }
733
OLDNEW
« no previous file with comments | « chrome/browser/autocomplete/autocomplete.h ('k') | chrome/browser/autocomplete/autocomplete_controller.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698