| OLD | NEW |
| 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/contact_provider_chromeos.h" | 5 #include "chrome/browser/autocomplete/contact_provider_chromeos.h" |
| 6 | 6 |
| 7 #include <cmath> |
| 7 #include <map> | 8 #include <map> |
| 8 #include <string> | 9 #include <string> |
| 9 #include <vector> | 10 #include <vector> |
| 10 | 11 |
| 11 #include "base/memory/scoped_ptr.h" | 12 #include "base/memory/scoped_ptr.h" |
| 12 #include "base/message_loop.h" | 13 #include "base/message_loop.h" |
| 14 #include "base/string_number_conversions.h" |
| 13 #include "base/string16.h" | 15 #include "base/string16.h" |
| 14 #include "base/utf_string_conversions.h" | 16 #include "base/utf_string_conversions.h" |
| 15 #include "chrome/browser/autocomplete/autocomplete_input.h" | 17 #include "chrome/browser/autocomplete/autocomplete_input.h" |
| 16 #include "chrome/browser/autocomplete/autocomplete_match.h" | 18 #include "chrome/browser/autocomplete/autocomplete_match.h" |
| 17 #include "chrome/browser/autocomplete/autocomplete_provider.h" | 19 #include "chrome/browser/autocomplete/autocomplete_provider.h" |
| 18 #include "chrome/browser/chromeos/contacts/contact.pb.h" | 20 #include "chrome/browser/chromeos/contacts/contact.pb.h" |
| 19 #include "chrome/browser/chromeos/contacts/contact_manager_stub.h" | 21 #include "chrome/browser/chromeos/contacts/contact_manager_stub.h" |
| 20 #include "chrome/browser/chromeos/contacts/contact_test_util.h" | 22 #include "chrome/browser/chromeos/contacts/contact_test_util.h" |
| 21 #include "chrome/test/base/testing_browser_process.h" | 23 #include "chrome/test/base/testing_browser_process.h" |
| 22 #include "chrome/test/base/testing_profile.h" | 24 #include "chrome/test/base/testing_profile.h" |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 66 contact_provider_->Start( | 68 contact_provider_->Start( |
| 67 AutocompleteInput(UTF8ToUTF16(utf8_text), | 69 AutocompleteInput(UTF8ToUTF16(utf8_text), |
| 68 string16(), // desired_tld | 70 string16(), // desired_tld |
| 69 false, // prevent_inline_autocomplete | 71 false, // prevent_inline_autocomplete |
| 70 false, // prefer_keyword | 72 false, // prefer_keyword |
| 71 false, // allow_exact_keyword_match | 73 false, // allow_exact_keyword_match |
| 72 AutocompleteInput::ALL_MATCHES), | 74 AutocompleteInput::ALL_MATCHES), |
| 73 false); // minimal_changes | 75 false); // minimal_changes |
| 74 } | 76 } |
| 75 | 77 |
| 78 // Returns the contact ID in |match|'s additional info, or an empty string if |
| 79 // no ID is present. |
| 80 std::string GetContactIdFromMatch(const AutocompleteMatch& match) { |
| 81 AutocompleteMatch::AdditionalInfo::const_iterator it = |
| 82 match.additional_info.find(ContactProvider::kMatchContactIdKey); |
| 83 return it != match.additional_info.end() ? it->second : std::string(); |
| 84 } |
| 85 |
| 76 // Returns pointers to all of the Contact objects referenced in | 86 // Returns pointers to all of the Contact objects referenced in |
| 77 // |contact_provider_|'s current results. | 87 // |contact_provider_|'s current results. |
| 78 contacts::ContactPointers GetMatchedContacts() { | 88 contacts::ContactPointers GetMatchedContacts() { |
| 79 contacts::ContactPointers contacts; | 89 contacts::ContactPointers contacts; |
| 80 const ACMatches& matches = contact_provider_->matches(); | 90 const ACMatches& matches = contact_provider_->matches(); |
| 81 for (size_t i = 0; i < matches.size(); ++i) { | 91 for (size_t i = 0; i < matches.size(); ++i) { |
| 82 std::map<std::string, std::string>::const_iterator id_it = | 92 const contacts::Contact* contact = contact_manager_->GetContactById( |
| 83 matches[i].additional_info.find(ContactProvider::kMatchContactIdKey); | 93 profile_, GetContactIdFromMatch(matches[i])); |
| 84 CHECK(id_it != matches[i].additional_info.end()); | 94 if (contact) |
| 85 const contacts::Contact* contact = | 95 contacts.push_back(contact); |
| 86 contact_manager_->GetContactById(profile_, id_it->second); | 96 else |
| 87 CHECK(contact) << "Unable to find contact with ID " << id_it->second; | 97 LOG(ERROR) << "Unable to find contact for match " << i; |
| 88 contacts.push_back(contact); | |
| 89 } | 98 } |
| 90 return contacts; | 99 return contacts; |
| 91 } | 100 } |
| 92 | 101 |
| 93 // Returns a semicolon-separated string containing string representations (as | 102 // Returns a semicolon-separated string containing string representations (as |
| 94 // provided by AutocompleteMatch::ClassificationsToString()) of the | 103 // provided by AutocompleteMatch::ClassificationsToString()) of the |
| 95 // |contents_class| fields of all current matches. Results are sorted by | 104 // |contents_class| fields of all current matches. Results are sorted by |
| 96 // contact ID. | 105 // contact ID. |
| 97 std::string GetMatchClassifications() { | 106 std::string GetMatchClassifications() { |
| 98 typedef std::map<std::string, std::string> StringMap; | 107 typedef std::map<std::string, std::string> StringMap; |
| 99 StringMap contact_id_classifications; | 108 StringMap contact_id_classifications; |
| 100 const ACMatches& matches = contact_provider_->matches(); | 109 const ACMatches& matches = contact_provider_->matches(); |
| 101 for (size_t i = 0; i < matches.size(); ++i) { | 110 for (size_t i = 0; i < matches.size(); ++i) { |
| 102 std::map<std::string, std::string>::const_iterator id_it = | 111 std::string id = GetContactIdFromMatch(matches[i]); |
| 103 matches[i].additional_info.find(ContactProvider::kMatchContactIdKey); | 112 if (id.empty()) { |
| 104 CHECK(id_it != matches[i].additional_info.end()); | 113 LOG(ERROR) << "Match " << i << " lacks contact ID"; |
| 105 contact_id_classifications[id_it->second] = | 114 } else { |
| 106 AutocompleteMatch::ClassificationsToString(matches[i].contents_class); | 115 contact_id_classifications[id] = AutocompleteMatch:: |
| 116 ClassificationsToString(matches[i].contents_class); |
| 117 } |
| 107 } | 118 } |
| 108 | 119 |
| 109 std::string result; | 120 std::string result; |
| 110 for (StringMap::const_iterator it = contact_id_classifications.begin(); | 121 for (StringMap::const_iterator it = contact_id_classifications.begin(); |
| 111 it != contact_id_classifications.end(); ++it) { | 122 it != contact_id_classifications.end(); ++it) { |
| 112 if (!result.empty()) | 123 if (!result.empty()) |
| 113 result += ";"; | 124 result += ";"; |
| 114 result += it->second; | 125 result += it->second; |
| 115 } | 126 } |
| 116 return result; | 127 return result; |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 220 contacts::test::VarContactsToString(1, contact.get()), | 231 contacts::test::VarContactsToString(1, contact.get()), |
| 221 contacts::test::ContactsToString(GetMatchedContacts())); | 232 contacts::test::ContactsToString(GetMatchedContacts())); |
| 222 EXPECT_EQ("0,2,5,0", GetMatchClassifications()); | 233 EXPECT_EQ("0,2,5,0", GetMatchClassifications()); |
| 223 | 234 |
| 224 StartQuery("adelsvard"); | 235 StartQuery("adelsvard"); |
| 225 EXPECT_EQ( | 236 EXPECT_EQ( |
| 226 contacts::test::VarContactsToString(1, contact.get()), | 237 contacts::test::VarContactsToString(1, contact.get()), |
| 227 contacts::test::ContactsToString(GetMatchedContacts())); | 238 contacts::test::ContactsToString(GetMatchedContacts())); |
| 228 EXPECT_EQ("0,0,6,2", GetMatchClassifications()); | 239 EXPECT_EQ("0,0,6,2", GetMatchClassifications()); |
| 229 } | 240 } |
| 241 |
| 242 TEST_F(ContactProviderTest, Relevance) { |
| 243 // Create more contacts than the maximum number of results that an |
| 244 // AutocompleteProvider should return. Give them all the same family name and |
| 245 // ascending affinities from 0.0 to 1.0. |
| 246 const size_t kNumContacts = AutocompleteProvider::kMaxMatches + 1; |
| 247 const std::string kFamilyName = "Jones"; |
| 248 |
| 249 ScopedVector<contacts::Contact> contacts; |
| 250 contacts::ContactPointers contact_pointers; |
| 251 for (size_t i = 0; i < kNumContacts; ++i) { |
| 252 contacts::Contact* contact = new contacts::Contact; |
| 253 std::string id_string = base::IntToString(static_cast<int>(i)); |
| 254 InitContact(id_string, id_string, kFamilyName, |
| 255 id_string + " " + kFamilyName, contact); |
| 256 contact->set_affinity(static_cast<float>(i) / kNumContacts); |
| 257 contacts.push_back(contact); |
| 258 contact_pointers.push_back(contact); |
| 259 } |
| 260 |
| 261 contact_manager_->SetContacts(contact_pointers); |
| 262 contact_manager_->NotifyObserversAboutUpdatedContacts(); |
| 263 |
| 264 // Do a search for the family name and check that the total number of results |
| 265 // is limited as expected and that the results are ordered by descending |
| 266 // affinity. |
| 267 StartQuery(kFamilyName); |
| 268 const ACMatches& matches = contact_provider_->matches(); |
| 269 ASSERT_EQ(AutocompleteProvider::kMaxMatches, matches.size()); |
| 270 |
| 271 int previous_relevance = 0; |
| 272 for (size_t i = 0; i < matches.size(); ++i) { |
| 273 const contacts::Contact& exp_contact = |
| 274 *(contacts[kNumContacts - 1 - i]); |
| 275 std::string match_id = GetContactIdFromMatch(matches[i]); |
| 276 EXPECT_EQ(exp_contact.contact_id(), match_id) |
| 277 << "Expected contact ID " << exp_contact.contact_id() |
| 278 << " for match " << i << " but got " << match_id << " instead"; |
| 279 if (i > 0) { |
| 280 EXPECT_LE(matches[i].relevance, previous_relevance) |
| 281 << "Match " << i << " has greater relevance than previous match"; |
| 282 } |
| 283 previous_relevance = matches[i].relevance; |
| 284 } |
| 285 } |
| OLD | NEW |