| 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 |