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 "components/omnibox/browser/shortcuts_provider.h" | 5 #include "components/omnibox/browser/shortcuts_provider.h" |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 #include <string> | 8 #include <string> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
11 #include "base/macros.h" | 11 #include "base/macros.h" |
12 #include "base/memory/ref_counted.h" | 12 #include "base/memory/ref_counted.h" |
13 #include "base/message_loop/message_loop.h" | 13 #include "base/message_loop/message_loop.h" |
14 #include "base/strings/utf_string_conversions.h" | 14 #include "base/strings/utf_string_conversions.h" |
15 #include "chrome/browser/autocomplete/chrome_autocomplete_provider_client.h" | 15 #include "chrome/browser/autocomplete/chrome_autocomplete_provider_client.h" |
16 #include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h" | 16 #include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h" |
17 #include "chrome/browser/autocomplete/shortcuts_backend_factory.h" | 17 #include "chrome/browser/autocomplete/shortcuts_backend_factory.h" |
18 #include "chrome/test/base/testing_profile.h" | 18 #include "chrome/test/base/testing_profile.h" |
19 #include "components/history/core/browser/history_service.h" | 19 #include "components/history/core/browser/history_service.h" |
20 #include "components/omnibox/browser/autocomplete_input.h" | 20 #include "components/omnibox/browser/autocomplete_input.h" |
21 #include "components/omnibox/browser/autocomplete_match.h" | 21 #include "components/omnibox/browser/autocomplete_match.h" |
22 #include "components/omnibox/browser/autocomplete_result.h" | 22 #include "components/omnibox/browser/autocomplete_result.h" |
23 #include "components/omnibox/browser/shortcuts_backend.h" | 23 #include "components/omnibox/browser/shortcuts_backend.h" |
| 24 #include "components/omnibox/browser/shortcuts_provider_test_util.h" |
24 #include "content/public/browser/notification_service.h" | 25 #include "content/public/browser/notification_service.h" |
25 #include "content/public/test/test_browser_thread.h" | 26 #include "content/public/test/test_browser_thread.h" |
26 #include "testing/gtest/include/gtest/gtest.h" | 27 #include "testing/gtest/include/gtest/gtest.h" |
27 | 28 |
28 #if defined(ENABLE_EXTENSIONS) | 29 #if defined(ENABLE_EXTENSIONS) |
29 #include "extensions/browser/notification_types.h" | 30 #include "extensions/browser/notification_types.h" |
30 #include "extensions/common/extension.h" | 31 #include "extensions/common/extension.h" |
31 #include "extensions/common/extension_builder.h" | 32 #include "extensions/common/extension_builder.h" |
32 #endif | 33 #endif |
33 | 34 |
34 using base::ASCIIToUTF16; | 35 using base::ASCIIToUTF16; |
35 | 36 |
36 // TestShortcutInfo ----------------------------------------------------------- | |
37 | |
38 namespace { | 37 namespace { |
39 | 38 |
40 struct TestShortcutInfo { | 39 struct TestShortcutInfo shortcut_test_db[] = { |
41 std::string guid; | 40 {"BD85DBA2-8C29-49F9-84AE-48E1E90880F1", "echo echo", "echo echo", |
42 std::string text; | 41 "chrome-extension://cedabbhfglmiikkmdgcpjdkocfcmbkee/?q=echo", |
43 std::string fill_into_edit; | 42 "Run Echo command: echo", "0,0", "Echo", "0,4", ui::PAGE_TRANSITION_TYPED, |
44 std::string destination_url; | 43 AutocompleteMatchType::EXTENSION_APP, "echo", 1, 1}, |
45 std::string contents; | |
46 std::string contents_class; | |
47 std::string description; | |
48 std::string description_class; | |
49 ui::PageTransition transition; | |
50 AutocompleteMatch::Type type; | |
51 std::string keyword; | |
52 int days_from_now; | |
53 int number_of_hits; | |
54 } shortcut_test_db[] = { | |
55 { "BD85DBA2-8C29-49F9-84AE-48E1E90880F1", "echo echo", "echo echo", | |
56 "chrome-extension://cedabbhfglmiikkmdgcpjdkocfcmbkee/?q=echo", | |
57 "Run Echo command: echo", "0,0", "Echo", "0,4", | |
58 ui::PAGE_TRANSITION_TYPED, AutocompleteMatchType::EXTENSION_APP, | |
59 "echo", 1, 1 }, | |
60 }; | 44 }; |
61 | 45 |
62 } // namespace | 46 } // namespace |
63 | 47 |
64 // ShortcutsProviderExtensionTest --------------------------------------------- | 48 // ShortcutsProviderExtensionTest --------------------------------------------- |
65 | 49 |
66 class ShortcutsProviderExtensionTest : public testing::Test { | 50 class ShortcutsProviderExtensionTest : public testing::Test { |
67 public: | 51 public: |
68 ShortcutsProviderExtensionTest(); | 52 ShortcutsProviderExtensionTest(); |
69 | 53 |
70 protected: | 54 protected: |
71 typedef std::pair<std::string, bool> ExpectedURLAndAllowedToBeDefault; | |
72 typedef std::vector<ExpectedURLAndAllowedToBeDefault> ExpectedURLs; | |
73 | |
74 class SetShouldContain | |
75 : public std::unary_function<const ExpectedURLAndAllowedToBeDefault&, | |
76 std::set<std::string> > { | |
77 public: | |
78 explicit SetShouldContain(const ACMatches& matched_urls); | |
79 | |
80 void operator()(const ExpectedURLAndAllowedToBeDefault& expected); | |
81 std::set<ExpectedURLAndAllowedToBeDefault> Leftovers() const { | |
82 return matches_; | |
83 } | |
84 | |
85 private: | |
86 std::set<ExpectedURLAndAllowedToBeDefault> matches_; | |
87 }; | |
88 | |
89 void SetUp() override; | 55 void SetUp() override; |
90 void TearDown() override; | 56 void TearDown() override; |
91 | 57 |
92 // Fills test data into the provider. | |
93 void FillData(TestShortcutInfo* db, size_t db_size); | |
94 | |
95 // Runs an autocomplete query on |text| with the provided | |
96 // |prevent_inline_autocomplete| setting and checks to see that the returned | |
97 // results' destination URLs match those provided. |expected_urls| does not | |
98 // need to be in sorted order, but |expected_top_result| should be the top | |
99 // match, and it should have inline autocompletion | |
100 // |top_result_inline_autocompletion|. | |
101 void RunTest(const base::string16 text, | |
102 bool prevent_inline_autocomplete, | |
103 const ExpectedURLs& expected_urls, | |
104 std::string expected_top_result, | |
105 base::string16 top_result_inline_autocompletion); | |
106 | |
107 base::MessageLoopForUI message_loop_; | 58 base::MessageLoopForUI message_loop_; |
108 content::TestBrowserThread ui_thread_; | 59 content::TestBrowserThread ui_thread_; |
109 content::TestBrowserThread file_thread_; | 60 content::TestBrowserThread file_thread_; |
110 | |
111 TestingProfile profile_; | 61 TestingProfile profile_; |
112 ChromeAutocompleteProviderClient client_; | 62 ChromeAutocompleteProviderClient client_; |
113 | |
114 ACMatches ac_matches_; // The resulting matches after running RunTest. | |
115 | |
116 scoped_refptr<ShortcutsBackend> backend_; | 63 scoped_refptr<ShortcutsBackend> backend_; |
117 scoped_refptr<ShortcutsProvider> provider_; | 64 scoped_refptr<ShortcutsProvider> provider_; |
118 }; | 65 }; |
119 | 66 |
120 ShortcutsProviderExtensionTest::ShortcutsProviderExtensionTest() | 67 ShortcutsProviderExtensionTest::ShortcutsProviderExtensionTest() |
121 : ui_thread_(content::BrowserThread::UI, &message_loop_), | 68 : ui_thread_(content::BrowserThread::UI, &message_loop_), |
122 file_thread_(content::BrowserThread::FILE, &message_loop_), | 69 file_thread_(content::BrowserThread::FILE, &message_loop_), |
123 client_(&profile_) { | 70 client_(&profile_) { |
124 } | 71 } |
125 | 72 |
126 void ShortcutsProviderExtensionTest::SetUp() { | 73 void ShortcutsProviderExtensionTest::SetUp() { |
127 ShortcutsBackendFactory::GetInstance()->SetTestingFactoryAndUse( | 74 ShortcutsBackendFactory::GetInstance()->SetTestingFactoryAndUse( |
128 &profile_, &ShortcutsBackendFactory::BuildProfileNoDatabaseForTesting); | 75 &profile_, &ShortcutsBackendFactory::BuildProfileNoDatabaseForTesting); |
129 backend_ = ShortcutsBackendFactory::GetForProfile(&profile_); | 76 backend_ = ShortcutsBackendFactory::GetForProfile(&profile_); |
130 ASSERT_TRUE(backend_.get()); | 77 ASSERT_TRUE(backend_.get()); |
131 ASSERT_TRUE(profile_.CreateHistoryService(true, false)); | 78 ASSERT_TRUE(profile_.CreateHistoryService(true, false)); |
132 provider_ = new ShortcutsProvider(&client_); | 79 provider_ = new ShortcutsProvider(&client_); |
133 FillData(shortcut_test_db, arraysize(shortcut_test_db)); | 80 PopulateShortcutsBackendWithTestShortcutData(client_.GetShortcutsBackend(), |
| 81 shortcut_test_db, |
| 82 arraysize(shortcut_test_db)); |
134 } | 83 } |
135 | 84 |
136 void ShortcutsProviderExtensionTest::TearDown() { | 85 void ShortcutsProviderExtensionTest::TearDown() { |
137 // Run all pending tasks or else some threads hold on to the message loop | 86 // Run all pending tasks or else some threads hold on to the message loop |
138 // and prevent it from being deleted. | 87 // and prevent it from being deleted. |
139 message_loop_.RunUntilIdle(); | 88 message_loop_.RunUntilIdle(); |
140 profile_.DestroyHistoryService(); | 89 profile_.DestroyHistoryService(); |
141 provider_ = NULL; | 90 provider_ = NULL; |
142 } | 91 } |
143 | 92 |
144 void ShortcutsProviderExtensionTest::FillData( | |
145 TestShortcutInfo* db, size_t db_size) { | |
146 DCHECK(provider_.get()); | |
147 size_t expected_size = backend_->shortcuts_map().size() + db_size; | |
148 for (size_t i = 0; i < db_size; ++i) { | |
149 const TestShortcutInfo& cur = db[i]; | |
150 ShortcutsDatabase::Shortcut shortcut( | |
151 cur.guid, ASCIIToUTF16(cur.text), | |
152 ShortcutsDatabase::Shortcut::MatchCore( | |
153 ASCIIToUTF16(cur.fill_into_edit), GURL(cur.destination_url), | |
154 ASCIIToUTF16(cur.contents), cur.contents_class, | |
155 ASCIIToUTF16(cur.description), cur.description_class, | |
156 cur.transition, cur.type, ASCIIToUTF16(cur.keyword)), | |
157 base::Time::Now() - base::TimeDelta::FromDays(cur.days_from_now), | |
158 cur.number_of_hits); | |
159 backend_->AddShortcut(shortcut); | |
160 } | |
161 EXPECT_EQ(expected_size, backend_->shortcuts_map().size()); | |
162 } | |
163 | |
164 ShortcutsProviderExtensionTest::SetShouldContain::SetShouldContain( | |
165 const ACMatches& matched_urls) { | |
166 for (ACMatches::const_iterator iter = matched_urls.begin(); | |
167 iter != matched_urls.end(); ++iter) | |
168 matches_.insert(ExpectedURLAndAllowedToBeDefault( | |
169 iter->destination_url.spec(), iter->allowed_to_be_default_match)); | |
170 } | |
171 | |
172 void ShortcutsProviderExtensionTest::SetShouldContain::operator()( | |
173 const ExpectedURLAndAllowedToBeDefault& expected) { | |
174 EXPECT_EQ(1U, matches_.erase(expected)); | |
175 } | |
176 | |
177 void ShortcutsProviderExtensionTest::RunTest( | |
178 const base::string16 text, | |
179 bool prevent_inline_autocomplete, | |
180 const ExpectedURLs& expected_urls, | |
181 std::string expected_top_result, | |
182 base::string16 top_result_inline_autocompletion) { | |
183 base::MessageLoop::current()->RunUntilIdle(); | |
184 AutocompleteInput input(text, base::string16::npos, std::string(), GURL(), | |
185 metrics::OmniboxEventProto::INVALID_SPEC, | |
186 prevent_inline_autocomplete, false, true, true, false, | |
187 ChromeAutocompleteSchemeClassifier(&profile_)); | |
188 provider_->Start(input, false); | |
189 EXPECT_TRUE(provider_->done()); | |
190 | |
191 ac_matches_ = provider_->matches(); | |
192 | |
193 // We should have gotten back at most AutocompleteProvider::kMaxMatches. | |
194 EXPECT_LE(ac_matches_.size(), AutocompleteProvider::kMaxMatches); | |
195 | |
196 // If the number of expected and actual matches aren't equal then we need | |
197 // test no further, but let's do anyway so that we know which URLs failed. | |
198 EXPECT_EQ(expected_urls.size(), ac_matches_.size()); | |
199 | |
200 // Verify that all expected URLs were found and that all found URLs | |
201 // were expected. | |
202 std::set<ExpectedURLAndAllowedToBeDefault> Leftovers = | |
203 for_each(expected_urls.begin(), expected_urls.end(), | |
204 SetShouldContain(ac_matches_)).Leftovers(); | |
205 EXPECT_EQ(0U, Leftovers.size()); | |
206 | |
207 // See if we got the expected top scorer. | |
208 if (!ac_matches_.empty()) { | |
209 std::partial_sort(ac_matches_.begin(), ac_matches_.begin() + 1, | |
210 ac_matches_.end(), AutocompleteMatch::MoreRelevant); | |
211 EXPECT_EQ(expected_top_result, ac_matches_[0].destination_url.spec()); | |
212 EXPECT_EQ(top_result_inline_autocompletion, | |
213 ac_matches_[0].inline_autocompletion); | |
214 } | |
215 } | |
216 | |
217 // Actual tests --------------------------------------------------------------- | 93 // Actual tests --------------------------------------------------------------- |
218 | 94 |
219 #if defined(ENABLE_EXTENSIONS) | 95 #if defined(ENABLE_EXTENSIONS) |
220 TEST_F(ShortcutsProviderExtensionTest, Extension) { | 96 TEST_F(ShortcutsProviderExtensionTest, Extension) { |
221 // Try an input string that matches an extension URL. | 97 // Try an input string that matches an extension URL. |
222 base::string16 text(ASCIIToUTF16("echo")); | 98 base::string16 text(ASCIIToUTF16("echo")); |
223 std::string expected_url( | 99 std::string expected_url( |
224 "chrome-extension://cedabbhfglmiikkmdgcpjdkocfcmbkee/?q=echo"); | 100 "chrome-extension://cedabbhfglmiikkmdgcpjdkocfcmbkee/?q=echo"); |
225 ExpectedURLs expected_urls; | 101 ShortcutExpectedURLs expected_urls; |
226 expected_urls.push_back(ExpectedURLAndAllowedToBeDefault(expected_url, true)); | 102 expected_urls.push_back( |
227 RunTest(text, false, expected_urls, expected_url, ASCIIToUTF16(" echo")); | 103 ShortcutExpectedURLAndAllowedToBeDefault(expected_url, true)); |
| 104 |
| 105 RunShortcutsProviderTest(provider_, text, false, expected_urls, expected_url, |
| 106 ASCIIToUTF16(" echo")); |
228 | 107 |
229 // Claim the extension has been unloaded. | 108 // Claim the extension has been unloaded. |
230 scoped_refptr<const extensions::Extension> extension = | 109 scoped_refptr<const extensions::Extension> extension = |
231 extensions::ExtensionBuilder() | 110 extensions::ExtensionBuilder() |
232 .SetManifest(std::move(extensions::DictionaryBuilder() | 111 .SetManifest(std::move(extensions::DictionaryBuilder() |
233 .Set("name", "Echo") | 112 .Set("name", "Echo") |
234 .Set("version", "1.0"))) | 113 .Set("version", "1.0"))) |
235 .SetID("cedabbhfglmiikkmdgcpjdkocfcmbkee") | 114 .SetID("cedabbhfglmiikkmdgcpjdkocfcmbkee") |
236 .Build(); | 115 .Build(); |
237 extensions::UnloadedExtensionInfo details( | 116 extensions::UnloadedExtensionInfo details( |
238 extension.get(), extensions::UnloadedExtensionInfo::REASON_UNINSTALL); | 117 extension.get(), extensions::UnloadedExtensionInfo::REASON_UNINSTALL); |
239 content::NotificationService::current()->Notify( | 118 content::NotificationService::current()->Notify( |
240 extensions::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED, | 119 extensions::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED, |
241 content::Source<Profile>(&profile_), | 120 content::Source<Profile>(&profile_), |
242 content::Details<extensions::UnloadedExtensionInfo>(&details)); | 121 content::Details<extensions::UnloadedExtensionInfo>(&details)); |
243 | 122 |
244 // Now the URL should have disappeared. | 123 // Now the URL should have disappeared. |
245 RunTest(text, false, ExpectedURLs(), std::string(), base::string16()); | 124 RunShortcutsProviderTest(provider_, text, false, ShortcutExpectedURLs(), |
| 125 std::string(), base::string16()); |
246 } | 126 } |
247 #endif | 127 #endif |
OLD | NEW |