diff options
-rw-r--r-- | chrome/browser/search_engines/template_url.cc | 29 | ||||
-rw-r--r-- | chrome/browser/search_engines/template_url.h | 19 | ||||
-rw-r--r-- | chrome/browser/search_engines/template_url_unittest.cc | 71 |
3 files changed, 104 insertions, 15 deletions
diff --git a/chrome/browser/search_engines/template_url.cc b/chrome/browser/search_engines/template_url.cc index 26da6fa..9ff827c 100644 --- a/chrome/browser/search_engines/template_url.cc +++ b/chrome/browser/search_engines/template_url.cc @@ -97,6 +97,7 @@ bool TemplateURLRef::ParseParameter(size_t start, length--; } std::wstring parameter(url->substr(start + 1, length)); + std::wstring full_parameter(url->substr(start, end - start + 1)); // Remove the parameter from the string. url->erase(start, end - start + 1); if (parameter == kSearchTermsParameter) { @@ -137,9 +138,9 @@ bool TemplateURLRef::ParseParameter(size_t start, } else if (parameter == kGoogleUnescapedSearchTermsParameter) { replacements->push_back(Replacement(GOOGLE_UNESCAPED_SEARCH_TERMS, static_cast<int>(start))); - } else if (!optional) { - // Unknown required parameter. No idea what to replace this with, - // so fail. + } else { + // It can be some garbage but can also be a javascript block. Put it back. + url->insert(start, full_parameter); return false; } return true; @@ -153,14 +154,22 @@ std::wstring TemplateURLRef::ParseURL(const std::wstring& url, for (size_t last = 0; last != std::string::npos; ) { last = parsed_url.find(kStartParameter, last); if (last != std::string::npos) { - size_t endTemplate = parsed_url.find(kEndParameter, last); - if (endTemplate != std::string::npos) { - if (!ParseParameter(last, endTemplate, &parsed_url, replacements)) { - // Not a valid parameter, return. - return std::wstring(); + size_t template_end = parsed_url.find(kEndParameter, last); + if (template_end != std::string::npos) { + // Since we allow Javascript in the URL, {} pairs could be nested. Match + // only leaf pairs with supported parameters. + size_t next_template_start = parsed_url.find(kStartParameter, last + 1); + if (next_template_start == std::string::npos || + next_template_start > template_end) { + // If successful, ParseParameter erases from the string as such no + // need to update |last|. If failed, move |last| to the end of pair. + if (!ParseParameter(last, template_end, &parsed_url, replacements)) { + // |template_end| + 1 may be beyond the end of the string. + last = template_end; + } + } else { + last = next_template_start; } - // ParseParamter erases from the string, as such we don't need - // to update last. } else { // Open brace without a closing brace, return. return std::wstring(); diff --git a/chrome/browser/search_engines/template_url.h b/chrome/browser/search_engines/template_url.h index 9462363..90cd734 100644 --- a/chrome/browser/search_engines/template_url.h +++ b/chrome/browser/search_engines/template_url.h @@ -5,10 +5,12 @@ #ifndef CHROME_BROWSER_SEARCH_ENGINES_TEMPLATE_URL_H_ #define CHROME_BROWSER_SEARCH_ENGINES_TEMPLATE_URL_H_ +#include <string> #include <vector> #include "base/time.h" #include "googleurl/src/gurl.h" +#include "testing/gtest/include/gtest/gtest_prod.h" class TemplateURL; @@ -111,6 +113,13 @@ class TemplateURLRef { friend class TemplateURL; friend class TemplateURLModelTest; friend class TemplateURLTest; + FRIEND_TEST(TemplateURLTest, ParseParameterKnown); + FRIEND_TEST(TemplateURLTest, ParseParameterUnknown); + FRIEND_TEST(TemplateURLTest, ParseURLEmpty); + FRIEND_TEST(TemplateURLTest, ParseURLNoTemplateEnd); + FRIEND_TEST(TemplateURLTest, ParseURLNoKnownParameters); + FRIEND_TEST(TemplateURLTest, ParseURLTwoParameters); + FRIEND_TEST(TemplateURLTest, ParseURLNestedParameter); // Enumeration of the known types. enum ReplacementType { @@ -146,9 +155,11 @@ class TemplateURLRef { // range of the parameter in the url, including the braces. If the parameter // is valid, url is updated to reflect the appropriate parameter. If // the parameter is one of the known parameters an element is added to - // replacements indicating the type and range of the element. + // replacements indicating the type and range of the element. The original + // parameter is erased from the url. // - // If the parameter is not a known parameter, false is returned. + // If the parameter is not a known parameter, it's not erased and false is + // returned. bool ParseParameter(size_t start, size_t end, std::wstring* url, @@ -157,8 +168,8 @@ class TemplateURLRef { // Parses the specified url, replacing parameters as necessary. If // successful, valid is set to true, and the parsed url is returned. For all // known parameters that are encountered an entry is added to replacements. - // If there is an error parsing (unknown parameter, or bogus url), valid is - // set to false, and an empty string is returned. + // If there is an error parsing the url, valid is set to false, and an empty + // string is returned. std::wstring ParseURL(const std::wstring& url, Replacements* replacements, bool* valid) const; diff --git a/chrome/browser/search_engines/template_url_unittest.cc b/chrome/browser/search_engines/template_url_unittest.cc index 261adf0..fd468cb 100644 --- a/chrome/browser/search_engines/template_url_unittest.cc +++ b/chrome/browser/search_engines/template_url_unittest.cc @@ -369,7 +369,6 @@ TEST_F(TemplateURLTest, HostAndSearchTermKey) { // Single term with extra chars in value should match. { L"http://blah/?q=stock:{searchTerms}", "blah", "/", "q"}, - }; TemplateURL t_url; @@ -411,3 +410,73 @@ TEST_F(TemplateURLTest, Keyword) { EXPECT_FALSE(t_url.autogenerate_keyword()); EXPECT_EQ(L"foo", t_url.keyword()); } + +TEST_F(TemplateURLTest, ParseParameterKnown) { + std::wstring parsed_url(L"{searchTerms}"); + TemplateURLRef url_ref(parsed_url, 0, 0); + TemplateURLRef::Replacements replacements; + EXPECT_TRUE(url_ref.ParseParameter(0, 12, &parsed_url, &replacements)); + EXPECT_EQ(std::wstring(), parsed_url); + ASSERT_EQ(1U, replacements.size()); + EXPECT_EQ(0, replacements[0].index); + EXPECT_EQ(TemplateURLRef::SEARCH_TERMS, replacements[0].type); +} + +TEST_F(TemplateURLTest, ParseParameterUnknown) { + std::wstring parsed_url(L"{}"); + TemplateURLRef url_ref(parsed_url, 0, 0); + TemplateURLRef::Replacements replacements; + EXPECT_FALSE(url_ref.ParseParameter(0, 1, &parsed_url, &replacements)); + EXPECT_EQ(L"{}", parsed_url); + EXPECT_TRUE(replacements.empty()); +} + +TEST_F(TemplateURLTest, ParseURLEmpty) { + TemplateURLRef url_ref(L"", 0, 0); + TemplateURLRef::Replacements replacements; + bool valid = false; + EXPECT_EQ(std::wstring(), url_ref.ParseURL(L"", &replacements, &valid)); + EXPECT_TRUE(replacements.empty()); + EXPECT_TRUE(valid); +} + +TEST_F(TemplateURLTest, ParseURLNoTemplateEnd) { + TemplateURLRef url_ref(L"{", 0, 0); + TemplateURLRef::Replacements replacements; + bool valid = false; + EXPECT_EQ(std::wstring(), url_ref.ParseURL(L"{", &replacements, &valid)); + EXPECT_TRUE(replacements.empty()); + EXPECT_FALSE(valid); +} + +TEST_F(TemplateURLTest, ParseURLNoKnownParameters) { + TemplateURLRef url_ref(L"{}", 0, 0); + TemplateURLRef::Replacements replacements; + bool valid = false; + EXPECT_EQ(L"{}", url_ref.ParseURL(L"{}", &replacements, &valid)); + EXPECT_TRUE(replacements.empty()); + EXPECT_TRUE(valid); +} + +TEST_F(TemplateURLTest, ParseURLTwoParameters) { + TemplateURLRef url_ref(L"{}{{%s}}", 0, 0); + TemplateURLRef::Replacements replacements; + bool valid = false; + EXPECT_EQ(L"{}{}", + url_ref.ParseURL(L"{}{{searchTerms}}", &replacements, &valid)); + ASSERT_EQ(1U, replacements.size()); + EXPECT_EQ(3, replacements[0].index); + EXPECT_EQ(TemplateURLRef::SEARCH_TERMS, replacements[0].type); + EXPECT_TRUE(valid); +} + +TEST_F(TemplateURLTest, ParseURLNestedParameter) { + TemplateURLRef url_ref(L"{%s", 0, 0); + TemplateURLRef::Replacements replacements; + bool valid = false; + EXPECT_EQ(L"{", url_ref.ParseURL(L"{{searchTerms}", &replacements, &valid)); + ASSERT_EQ(1U, replacements.size()); + EXPECT_EQ(1, replacements[0].index); + EXPECT_EQ(TemplateURLRef::SEARCH_TERMS, replacements[0].type); + EXPECT_TRUE(valid); +} |