diff options
author | levin@chromium.org <levin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-06 23:17:59 +0000 |
---|---|---|
committer | levin@chromium.org <levin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-06 23:17:59 +0000 |
commit | fb9d1f424cfcc4d6967cc104299dc697f17b748e (patch) | |
tree | 324122237a921e4fb7e6c5ca7f28acfaabdd2dd1 /chrome/browser/search_engines | |
parent | f2e5eb9352fcb27bbc6af89c8f67a58fea0a30cf (diff) | |
download | chromium_src-fb9d1f424cfcc4d6967cc104299dc697f17b748e.zip chromium_src-fb9d1f424cfcc4d6967cc104299dc697f17b748e.tar.gz chromium_src-fb9d1f424cfcc4d6967cc104299dc697f17b748e.tar.bz2 |
A large part of this change is adding the 1st unit test for TemplateURLFetcher.
Also did some refactoring of TemplateURLFetcher to allow for a future
modification in which I make it able to start the load of TemplateURLModel and
wait for that to finish before processing the fetched url.
BUG=38475
TEST=unit_test --gtest_filter=TemplateURLFetcher*
Review URL: http://codereview.chromium.org/3548017
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@61727 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/search_engines')
3 files changed, 195 insertions, 75 deletions
diff --git a/chrome/browser/search_engines/template_url_fetcher.cc b/chrome/browser/search_engines/template_url_fetcher.cc index f5a3878..e6ab568 100644 --- a/chrome/browser/search_engines/template_url_fetcher.cc +++ b/chrome/browser/search_engines/template_url_fetcher.cc @@ -69,8 +69,11 @@ class TemplateURLFetcher::RequestDelegate : public URLFetcher::Delegate, const std::wstring keyword() const { return keyword_; } private: + void AddSearchProvider(); + URLFetcher url_fetcher_; TemplateURLFetcher* fetcher_; + scoped_ptr<TemplateURL> template_url_; std::wstring keyword_; const GURL osdd_url_; const GURL favicon_url_; @@ -94,81 +97,88 @@ void TemplateURLFetcher::RequestDelegate::OnURLFetchComplete( int response_code, const ResponseCookies& cookies, const std::string& data) { + template_url_.reset(new TemplateURL()); + + // Validation checks. // Make sure we can still replace the keyword, i.e. the fetch was successful. // If the OSDD file was loaded HTTP, we also have to check the response_code. // For other schemes, e.g. when the OSDD file is bundled with an extension, - // the response_code is not applicable and should be -1. + // the response_code is not applicable and should be -1. Also, ensure that + // the returned information results in a valid search URL. if (!status.is_success() || - ((response_code != -1) && (response_code != 200))) { + ((response_code != -1) && (response_code != 200)) || + !TemplateURLParser::Parse( + reinterpret_cast<const unsigned char*>(data.c_str()), + data.length(), + NULL, + template_url_.get()) || + !template_url_->url() || !template_url_->url()->SupportsReplacement()) { fetcher_->RequestCompleted(this); // WARNING: RequestCompleted deletes us. return; } + AddSearchProvider(); + // WARNING: AddSearchProvider deletes us. +} - scoped_ptr<TemplateURL> template_url(new TemplateURL()); - if (TemplateURLParser::Parse( - reinterpret_cast<const unsigned char*>(data.c_str()), - data.length(), - NULL, - template_url.get()) && - template_url->url() && template_url->url()->SupportsReplacement()) { - if (!autodetected_ || keyword_.empty()) { - // Generate new keyword from URL in OSDD for none autodetected case. - // Previous keyword was generated from URL where OSDD was placed and - // it gives wrong result when OSDD is located on third party site that - // has nothing in common with search engine in OSDD. - GURL keyword_url(template_url->url()->url()); - std::wstring new_keyword = TemplateURLModel::GenerateKeyword( - keyword_url, false); - if (!new_keyword.empty()) - keyword_ = new_keyword; - } - TemplateURLModel* model = fetcher_->profile()->GetTemplateURLModel(); - const TemplateURL* existing_url; - if (keyword_.empty() || - !model || !model->loaded() || - !model->CanReplaceKeyword(keyword_, GURL(template_url->url()->url()), - &existing_url)) { - if (autodetected_ || !model || !model->loaded()) { - fetcher_->RequestCompleted(this); - // WARNING: RequestCompleted deletes us. - return; - } - // If we're coming from JS (neither autodetected nor failure to load the - // template URL model) and this URL already exists in the model, we bring - // up the EditKeywordController to edit it. This is helpful feedback in - // the case of clicking a button twice, and annoying in the case of a - // page that calls AddSearchProvider() in JS without a user action. - keyword_.clear(); - existing_url = NULL; +void TemplateURLFetcher::RequestDelegate::AddSearchProvider() { + DCHECK(template_url_.get()); + if (!autodetected_ || keyword_.empty()) { + // Generate new keyword from URL in OSDD for none autodetected case. + // Previous keyword was generated from URL where OSDD was placed and + // it gives wrong result when OSDD is located on third party site that + // has nothing in common with search engine in OSDD. + GURL keyword_url(template_url_->url()->url()); + std::wstring new_keyword = TemplateURLModel::GenerateKeyword( + keyword_url, false); + if (!new_keyword.empty()) + keyword_ = new_keyword; + } + TemplateURLModel* model = fetcher_->profile()->GetTemplateURLModel(); + const TemplateURL* existing_url; + if (keyword_.empty() || + !model || !model->loaded() || + !model->CanReplaceKeyword(keyword_, GURL(template_url_->url()->url()), + &existing_url)) { + if (autodetected_ || !model || !model->loaded()) { + fetcher_->RequestCompleted(this); + // WARNING: RequestCompleted deletes us. + return; } + // If we're coming from JS (neither autodetected nor failure to load the + // template URL model) and this URL already exists in the model, we bring + // up the EditKeywordController to edit it. This is helpful feedback in + // the case of clicking a button twice, and annoying in the case of a + // page that calls AddSearchProvider() in JS without a user action. + keyword_.clear(); + existing_url = NULL; + } - if (existing_url) - model->Remove(existing_url); - - // The short name is what is shown to the user. We preserve original names - // since it is better when generated keyword in many cases. - template_url->set_keyword(keyword_); - template_url->set_originating_url(osdd_url_); - - // The page may have specified a URL to use for favicons, if not, set it. - if (!template_url->GetFavIconURL().is_valid()) - template_url->SetFavIconURL(favicon_url_); - - if (autodetected_) { - // Mark the keyword as replaceable so it can be removed if necessary. - template_url->set_safe_for_autoreplace(true); - model->Add(template_url.release()); - } else if (source_ && source_->delegate()) { - // Confirm addition and allow user to edit default choices. It's ironic - // that only *non*-autodetected additions get confirmed, but the user - // expects feedback that his action did something. - // The source TabContents' delegate takes care of adding the URL to the - // model, which takes ownership, or of deleting it if the add is - // cancelled. - source_->delegate()->ConfirmAddSearchProvider(template_url.release(), - fetcher_->profile()); - } + if (existing_url) + model->Remove(existing_url); + + // The short name is what is shown to the user. We preserve original names + // since it is better when generated keyword in many cases. + template_url_->set_keyword(keyword_); + template_url_->set_originating_url(osdd_url_); + + // The page may have specified a URL to use for favicons, if not, set it. + if (!template_url_->GetFavIconURL().is_valid()) + template_url_->SetFavIconURL(favicon_url_); + + if (autodetected_) { + // Mark the keyword as replaceable so it can be removed if necessary. + template_url_->set_safe_for_autoreplace(true); + model->Add(template_url_.release()); + } else if (source_ && source_->delegate()) { + // Confirm addition and allow user to edit default choices. It's ironic + // that only *non*-autodetected additions get confirmed, but the user + // expects feedback that his action did something. + // The source TabContents' delegate takes care of adding the URL to the + // model, which takes ownership, or of deleting it if the add is + // cancelled. + source_->delegate()->ConfirmAddSearchProvider(template_url_.release(), + fetcher_->profile()); } fetcher_->RequestCompleted(this); // WARNING: RequestCompleted deletes us. diff --git a/chrome/browser/search_engines/template_url_fetcher_unittest.cc b/chrome/browser/search_engines/template_url_fetcher_unittest.cc new file mode 100644 index 0000000..1b28b5a --- /dev/null +++ b/chrome/browser/search_engines/template_url_fetcher_unittest.cc @@ -0,0 +1,109 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/platform_thread.h" +#include "base/scoped_ptr.h" +#include "base/thread.h" +#include "chrome/browser/search_engines/template_url.h" +#include "chrome/browser/search_engines/template_url_fetcher.h" +#include "chrome/browser/search_engines/template_url_model.h" +#include "chrome/browser/search_engines/template_url_model_test_util.h" +#include "chrome/test/testing_profile.h" +#include "googleurl/src/gurl.h" +#include "net/test/test_server.h" +#include "testing/gtest/include/gtest/gtest.h" + +// Quits the current message loop as soon as there is a change to the +// TemplateURLModel. +class QuitOnChangedObserver : public TemplateURLModelObserver { + public: + explicit QuitOnChangedObserver(TemplateURLModel* model); + virtual ~QuitOnChangedObserver(); + + // TemplateURLModelObserver implemementation. + virtual void OnTemplateURLModelChanged(); + + private: + TemplateURLModel* model_; +}; + +QuitOnChangedObserver::QuitOnChangedObserver(TemplateURLModel* model) + : model_(model) { + model_->AddObserver(this); +} + +QuitOnChangedObserver::~QuitOnChangedObserver() { + model_->RemoveObserver(this); +} + +void QuitOnChangedObserver::OnTemplateURLModelChanged() { + MessageLoop::current()->Quit(); +} + +// Basic set-up for TemplateURLFetcher tests. +class TemplateURLFetcherTest : public testing::Test { + public: + TemplateURLFetcherTest(); + + virtual void SetUp() { + ASSERT_TRUE(test_server_.Start()); + test_util_.SetUp(); + + io_thread_.reset(new ChromeThread(ChromeThread::IO)); + base::Thread::Options options; + options.message_loop_type = MessageLoop::TYPE_IO; + io_thread_->StartWithOptions(options); + + test_util_.profile()->CreateTemplateURLFetcher(); + ASSERT_TRUE(test_util_.profile()->GetTemplateURLFetcher()); + + test_util_.profile()->CreateRequestContext(); + ASSERT_TRUE(test_util_.profile()->GetRequestContext()); + } + + virtual void TearDown() { + io_thread_->Stop(); + io_thread_.reset(); + test_util_.TearDown(); + } + + protected: + TemplateURLModelTestUtil test_util_; + net::TestServer test_server_; + scoped_ptr<ChromeThread> io_thread_; + + private: + DISALLOW_COPY_AND_ASSIGN(TemplateURLFetcherTest); +}; + +TemplateURLFetcherTest::TemplateURLFetcherTest() + : test_server_(net::TestServer::TYPE_HTTP, + FilePath(FILE_PATH_LITERAL("chrome/test/data"))) { +} + +TEST_F(TemplateURLFetcherTest, BasicTest) { + std::wstring keyword(L"test"); + + test_util_.ChangeModelToLoadState(); + test_util_.ResetObserverCount(); + ASSERT_FALSE(test_util_.model()->GetTemplateURLForKeyword(keyword)); + + GURL osdd_url = test_server_.GetURL("files/osdd/dictionary.xml"); + GURL favicon_url; + test_util_.profile()->GetTemplateURLFetcher()->ScheduleDownload( + keyword, osdd_url, favicon_url, NULL, true); + + { // Wait for the url to be downloaded. + QuitOnChangedObserver quit_on_changed_observer(test_util_.model()); + MessageLoop::current()->Run(); + } + + const TemplateURL* t_url = test_util_.model()->GetTemplateURLForKeyword( + keyword); + ASSERT_TRUE(t_url); + EXPECT_STREQ(L"http://dictionary.reference.com/browse/%s?r=75", + t_url->url()->DisplayURL().c_str()); + EXPECT_EQ(true, t_url->safe_for_autoreplace()); +} + diff --git a/chrome/browser/search_engines/template_url_model_test_util.cc b/chrome/browser/search_engines/template_url_model_test_util.cc index 35e87e8..480a6ee 100644 --- a/chrome/browser/search_engines/template_url_model_test_util.cc +++ b/chrome/browser/search_engines/template_url_model_test_util.cc @@ -123,8 +123,8 @@ TemplateURLModelTestUtil::~TemplateURLModelTestUtil() { void TemplateURLModelTestUtil::SetUp() { profile_.reset(new TemplateURLModelTestingProfile()); profile_->SetUp(); - model_.reset(new TestingTemplateURLModel(profile_.get())); - model_->AddObserver(this); + profile_->SetTemplateURLModel(new TestingTemplateURLModel(profile_.get())); + profile_->GetTemplateURLModel()->AddObserver(this); } void TemplateURLModelTestUtil::TearDown() { @@ -157,33 +157,34 @@ void TemplateURLModelTestUtil::BlockTillIOThreadProcessesRequests() { } void TemplateURLModelTestUtil::VerifyLoad() { - ASSERT_FALSE(model_->loaded()); - model_->Load(); + ASSERT_FALSE(model()->loaded()); + model()->Load(); BlockTillServiceProcessesRequests(); VerifyObserverCount(1); } void TemplateURLModelTestUtil::ChangeModelToLoadState() { - model_->ChangeToLoadedState(); + model()->ChangeToLoadedState(); // Initialize the web data service so that the database gets updated with // any changes made. - model_->service_ = profile_->GetWebDataService(Profile::EXPLICIT_ACCESS); + model()->service_ = profile_->GetWebDataService(Profile::EXPLICIT_ACCESS); } void TemplateURLModelTestUtil::ClearModel() { - model_.reset(NULL); + profile_->SetTemplateURLModel(NULL); } void TemplateURLModelTestUtil::ResetModel(bool verify_load) { - model_.reset(new TestingTemplateURLModel(profile_.get())); - model_->AddObserver(this); + profile_->SetTemplateURLModel(new TestingTemplateURLModel(profile_.get())); + model()->AddObserver(this); changed_count_ = 0; if (verify_load) VerifyLoad(); } std::wstring TemplateURLModelTestUtil::GetAndClearSearchTerm() { - return model_->GetAndClearSearchTerm(); + return + static_cast<TestingTemplateURLModel*>(model())->GetAndClearSearchTerm(); } void TemplateURLModelTestUtil::SetGoogleBaseURL( @@ -199,7 +200,7 @@ WebDataService* TemplateURLModelTestUtil::GetWebDataService() { } TemplateURLModel* TemplateURLModelTestUtil::model() const { - return model_.get(); + return profile_->GetTemplateURLModel(); } TestingProfile* TemplateURLModelTestUtil::profile() const { |