summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlevin@chromium.org <levin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-09-17 04:10:08 +0000
committerlevin@chromium.org <levin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-09-17 04:10:08 +0000
commit1c507659ce3d86b0c6705d07005da486574804c2 (patch)
tree20b7b44073f2addd3f2ece3f8fefc46f38276d62
parent8f3b5f4371c32005c9bb3ef868e9ae6568c42943 (diff)
downloadchromium_src-1c507659ce3d86b0c6705d07005da486574804c2.zip
chromium_src-1c507659ce3d86b0c6705d07005da486574804c2.tar.gz
chromium_src-1c507659ce3d86b0c6705d07005da486574804c2.tar.bz2
Implement SearchProviderInstallData.
Support for Google base URL will be in another patch. BUG=38475 TEST=unit_tests --gtest_filter=SearchProviderInstallDataTest* Review URL: http://codereview.chromium.org/3403008 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@59765 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/search_engines/search_provider_install_data.cc186
-rw-r--r--chrome/browser/search_engines/search_provider_install_data.h79
-rw-r--r--chrome/browser/search_engines/search_provider_install_data_unittest.cc201
-rw-r--r--chrome/browser/search_engines/template_url_prepopulate_data.cc3
-rw-r--r--chrome/chrome_browser.gypi1
-rw-r--r--chrome/chrome_tests.gypi1
6 files changed, 458 insertions, 13 deletions
diff --git a/chrome/browser/search_engines/search_provider_install_data.cc b/chrome/browser/search_engines/search_provider_install_data.cc
new file mode 100644
index 0000000..b137ece
--- /dev/null
+++ b/chrome/browser/search_engines/search_provider_install_data.cc
@@ -0,0 +1,186 @@
+// 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 "chrome/browser/search_engines/search_provider_install_data.h"
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/task.h"
+#include "chrome/browser/search_engines/search_host_to_urls_map.h"
+#include "chrome/browser/search_engines/search_terms_data.h"
+#include "chrome/browser/search_engines/template_url.h"
+#include "chrome/browser/search_engines/template_url_model.h"
+#include "chrome/browser/search_engines/util.h"
+#include "chrome/browser/webdata/web_data_service.h"
+
+typedef SearchHostToURLsMap::TemplateURLSet TemplateURLSet;
+
+namespace {
+
+// Implementation of SearchTermsData that may be used on the I/O thread.
+class IOThreadSearchTermsData : public SearchTermsData {
+ public:
+ IOThreadSearchTermsData() {}
+
+ // Implementation of SearchTermsData.
+ virtual std::string GoogleBaseURLValue() const;
+ virtual std::string GetApplicationLocale() const;
+#if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
+ virtual std::wstring GetRlzParameterValue() const {
+ // This value doesn't matter for our purposes.
+ return std::wstring();
+ }
+#endif
+
+ private:
+
+ DISALLOW_COPY_AND_ASSIGN(IOThreadSearchTermsData);
+};
+
+std::string IOThreadSearchTermsData::GoogleBaseURLValue() const {
+ // TODO(levin): fix this.
+ return "http://FIXME.FIXME/";
+}
+
+std::string IOThreadSearchTermsData::GetApplicationLocale() const {
+ // This value doesn't matter for our purposes.
+ return "yy";
+}
+
+// Indicates if the two inputs have the same security origin.
+// |requested_origin| should only be a security origin (no path, etc.).
+// It is ok if |template_url| is NULL.
+static bool IsSameOrigin(const GURL& requested_origin,
+ const TemplateURL* template_url,
+ const SearchTermsData& search_terms_data) {
+ DCHECK(requested_origin == requested_origin.GetOrigin());
+ return template_url && requested_origin ==
+ TemplateURLModel::GenerateSearchURLUsingTermsData(
+ template_url,
+ search_terms_data).GetOrigin();
+}
+
+} // namespace
+
+SearchProviderInstallData::SearchProviderInstallData(
+ WebDataService* web_service)
+ : web_service_(web_service),
+ load_handle_(0) {
+}
+
+SearchProviderInstallData::~SearchProviderInstallData() {
+ if (load_handle_) {
+ DCHECK(web_service_.get());
+ web_service_->CancelRequest(load_handle_);
+ }
+}
+
+void SearchProviderInstallData::CallWhenLoaded(Task* task) {
+ if (provider_map_.get()) {
+ task->Run();
+ delete task;
+ return;
+ }
+
+ task_queue_.Push(task);
+ if (load_handle_)
+ return;
+
+ if (web_service_.get())
+ load_handle_ = web_service_->GetKeywords(this);
+ else
+ OnLoadFailed();
+}
+
+SearchProviderInstallData::State SearchProviderInstallData::GetInstallState(
+ const GURL& requested_origin) {
+ DCHECK(provider_map_.get());
+
+ // First check to see if the origin is the default search provider.
+ if (requested_origin.spec() == default_search_origin_)
+ return INSTALLED_AS_DEFAULT;
+
+ // Is the url any search provider?
+ const TemplateURLSet* urls = provider_map_->GetURLsForHost(
+ requested_origin.host());
+ if (!urls)
+ return NOT_INSTALLED;
+
+ IOThreadSearchTermsData search_terms_data;
+ for (TemplateURLSet::const_iterator i = urls->begin();
+ i != urls->end(); ++i) {
+ const TemplateURL* template_url = *i;
+ if (IsSameOrigin(requested_origin, template_url, search_terms_data))
+ return INSTALLED_BUT_NOT_DEFAULT;
+ }
+ return NOT_INSTALLED;
+}
+
+void SearchProviderInstallData::OnWebDataServiceRequestDone(
+ WebDataService::Handle h,
+ const WDTypedResult* result) {
+ // Reset the load_handle so that we don't try and cancel the load in
+ // the destructor.
+ load_handle_ = 0;
+
+ if (!result) {
+ // Results are null if the database went away or (most likely) wasn't
+ // loaded.
+ OnLoadFailed();
+ return;
+ }
+
+ const TemplateURL* default_search_provider = NULL;
+ int new_resource_keyword_version = 0;
+ std::vector<TemplateURL*> extracted_template_urls;
+ GetSearchProvidersUsingKeywordResult(*result,
+ NULL,
+ NULL,
+ &extracted_template_urls,
+ &default_search_provider,
+ &new_resource_keyword_version);
+ template_urls_.get().insert(template_urls_.get().begin(),
+ extracted_template_urls.begin(),
+ extracted_template_urls.end());
+ IOThreadSearchTermsData search_terms_data;
+ provider_map_.reset(new SearchHostToURLsMap());
+ provider_map_->Init(template_urls_.get(), search_terms_data);
+ SetDefault(default_search_provider);
+ NotifyLoaded();
+}
+
+void SearchProviderInstallData::SetDefault(const TemplateURL* template_url) {
+ if (!template_url) {
+ default_search_origin_.clear();
+ return;
+ }
+
+ IOThreadSearchTermsData search_terms_data;
+ const GURL url(TemplateURLModel::GenerateSearchURLUsingTermsData(
+ template_url, search_terms_data));
+ if (!url.is_valid() || !url.has_host()) {
+ default_search_origin_.clear();
+ return;
+ }
+ default_search_origin_ = url.GetOrigin().spec();
+}
+
+void SearchProviderInstallData::OnLoadFailed() {
+ provider_map_.reset(new SearchHostToURLsMap());
+ IOThreadSearchTermsData search_terms_data;
+ provider_map_->Init(template_urls_.get(), search_terms_data);
+ SetDefault(NULL);
+ NotifyLoaded();
+}
+
+void SearchProviderInstallData::NotifyLoaded() {
+ task_queue_.Run();
+
+ // Since we expect this request to be rare, clear out the information. This
+ // also keeps the responses current as the search providers change.
+ provider_map_.reset();
+ SetDefault(NULL);
+}
diff --git a/chrome/browser/search_engines/search_provider_install_data.h b/chrome/browser/search_engines/search_provider_install_data.h
index 02595db..f6fbf3b 100644
--- a/chrome/browser/search_engines/search_provider_install_data.h
+++ b/chrome/browser/search_engines/search_provider_install_data.h
@@ -4,22 +4,29 @@
#ifndef CHROME_BROWSER_SEARCH_ENGINES_SEARCH_PROVIDER_INSTALL_DATA_H_
#define CHROME_BROWSER_SEARCH_ENGINES_SEARCH_PROVIDER_INSTALL_DATA_H_
+#pragma once
+#include <string>
+
+#include "base/basictypes.h"
#include "base/ref_counted.h"
+#include "base/scoped_ptr.h"
+#include "base/scoped_vector.h"
+#include "base/task_queue.h"
+#include "chrome/browser/webdata/web_data_service.h"
class GURL;
+class SearchHostToURLsMap;
+class Task;
+class TemplateURL;
-// Provides the search provider install state for the I/O thread.
-class SearchProviderInstallData
- : public base::RefCountedThreadSafe<SearchProviderInstallData> {
+// Provides the search provider install state for the I/O thread. It works by
+// loading the data on demand (when CallWhenLoaded is called) and then throwing
+// away the results after the callbacks are done, so the results are always up
+// to date with what is in the database.
+class SearchProviderInstallData : public WebDataServiceConsumer {
public:
enum State {
- // The install state cannot be determined at the moment.
- NOT_READY = -2,
-
- // Equates to an access denied error.
- DENIED = -1,
-
// The search provider is not installed.
NOT_INSTALLED = 0,
@@ -30,12 +37,58 @@ class SearchProviderInstallData
INSTALLED_AS_DEFAULT = 2
};
+ explicit SearchProviderInstallData(WebDataService* web_service);
+ ~SearchProviderInstallData();
+
+ // Use to determine when the search provider information is loaded.
+ // The callback may happen synchronously or asynchronously. This
+ // takes ownership of |task|. There is no need to do anything special
+ // to make it function (as it just relies on the normal I/O thread message
+ // loop).
+ void CallWhenLoaded(Task* task);
+
// Returns the search provider install state for the given origin.
- virtual State GetInstallState(const GURL& requested_origin) = 0;
+ // This should only be called while a task is called back from CallWhenLoaded.
+ State GetInstallState(const GURL& requested_origin);
+
+ private:
+ // WebDataServiceConsumer
+ // Notification that the keywords have been loaded.
+ // This is invoked from WebDataService, and should not be directly
+ // invoked.
+ virtual void OnWebDataServiceRequestDone(WebDataService::Handle h,
+ const WDTypedResult* result);
+
+ // Stores information about the default search provider.
+ void SetDefault(const TemplateURL* template_url);
+
+ // Sets up the loaded state and then lets clients know that the search
+ // provider install state has been loaded.
+ void OnLoadFailed();
+
+ // Does notifications to let clients know that the search provider
+ // install state has been loaded.
+ void NotifyLoaded();
+
+ // The list of tasks to call after the load has finished.
+ TaskQueue task_queue_;
+
+ // Service used to store entries.
+ scoped_refptr<WebDataService> web_service_;
+
+ // If non-zero, we're waiting on a load.
+ WebDataService::Handle load_handle_;
+
+ // Holds results of a load that was done using this class.
+ scoped_ptr<SearchHostToURLsMap> provider_map_;
+
+ // The list of template urls that are owned by the class.
+ ScopedVector<const TemplateURL> template_urls_;
+
+ // The security origin for the default search provider.
+ std::string default_search_origin_;
- protected:
- friend class base::RefCountedThreadSafe<SearchProviderInstallData>;
- virtual ~SearchProviderInstallData() {}
+ DISALLOW_COPY_AND_ASSIGN(SearchProviderInstallData);
};
#endif // CHROME_BROWSER_SEARCH_ENGINES_SEARCH_PROVIDER_INSTALL_DATA_H_
diff --git a/chrome/browser/search_engines/search_provider_install_data_unittest.cc b/chrome/browser/search_engines/search_provider_install_data_unittest.cc
new file mode 100644
index 0000000..1989a4c
--- /dev/null
+++ b/chrome/browser/search_engines/search_provider_install_data_unittest.cc
@@ -0,0 +1,201 @@
+// 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 <string>
+
+#include "base/basictypes.h"
+#include "base/message_loop.h"
+#include "base/ref_counted.h"
+#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/search_engines/search_provider_install_data.h"
+#include "chrome/browser/search_engines/template_url.h"
+#include "chrome/browser/search_engines/template_url_model.h"
+#include "chrome/browser/search_engines/template_url_model_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+// Create a TemplateURL. The caller owns the returned TemplateURL*.
+static TemplateURL* CreateTemplateURL(const std::string& url,
+ const std::wstring& keyword) {
+ TemplateURL* t_url = new TemplateURL();
+ t_url->SetURL(url, 0, 0);
+ t_url->set_keyword(keyword);
+ t_url->set_short_name(keyword);
+ return t_url;
+}
+
+// Test the SearchProviderInstallData::GetInstallState.
+class TestGetInstallState :
+ public base::RefCountedThreadSafe<TestGetInstallState> {
+ public:
+ explicit TestGetInstallState(WebDataService* web_data_service)
+ : install_data_(web_data_service),
+ main_loop_(NULL),
+ passed_(false) {
+ }
+
+ void set_search_provider_host(
+ const std::string& search_provider_host) {
+ search_provider_host_ = search_provider_host;
+ }
+
+ void set_default_search_provider_host(
+ const std::string& default_search_provider_host) {
+ default_search_provider_host_ = default_search_provider_host;
+ }
+
+ // Runs the test. Returns true if all passed. False if any failed.
+ bool RunTests(const ChromeThread& io_thread);
+
+ private:
+ friend class base::RefCountedThreadSafe<TestGetInstallState>;
+ ~TestGetInstallState();
+
+ // Starts the test run on the IO thread.
+ void StartTestOnIOThread();
+
+ // Callback for when SearchProviderInstallData is ready to have
+ // GetInstallState called. Runs all of the test cases.
+ void DoInstallStateTests();
+
+ // Does a verification for one url and its expected state.
+ void VerifyInstallState(SearchProviderInstallData::State expected_state,
+ const std::string& url);
+
+ SearchProviderInstallData install_data_;
+ MessageLoop* main_loop_;
+
+ // A host which should be a search provider but not the default.
+ std::string search_provider_host_;
+
+ // A host which should be a search provider but not the default.
+ std::string default_search_provider_host_;
+
+ // Used to indicate if DoInstallStateTests passed all test.
+ bool passed_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestGetInstallState);
+};
+
+bool TestGetInstallState::RunTests(const ChromeThread& io_thread) {
+ passed_ = true;
+
+ main_loop_ = MessageLoop::current();
+
+ io_thread.message_loop()->PostTask(
+ FROM_HERE,
+ NewRunnableMethod(this, &TestGetInstallState::StartTestOnIOThread));
+ // Run the current message loop. When the test is finished on the I/O thread,
+ // it invokes Quit, which unblocks this.
+ MessageLoop::current()->Run();
+ main_loop_ = NULL;
+
+ // Let the testing code know what the result is.
+ return passed_;
+}
+
+TestGetInstallState::~TestGetInstallState() {
+}
+
+void TestGetInstallState::StartTestOnIOThread() {
+ install_data_.CallWhenLoaded(
+ NewRunnableMethod(this,
+ &TestGetInstallState::DoInstallStateTests));
+}
+
+void TestGetInstallState::DoInstallStateTests() {
+ // Installed but not default.
+ VerifyInstallState(SearchProviderInstallData::INSTALLED_BUT_NOT_DEFAULT,
+ "http://" + search_provider_host_ + "/");
+ VerifyInstallState(SearchProviderInstallData::INSTALLED_BUT_NOT_DEFAULT,
+ "http://" + search_provider_host_ + ":80/");
+
+ // Not installed.
+ VerifyInstallState(SearchProviderInstallData::NOT_INSTALLED,
+ "http://" + search_provider_host_ + ":96/");
+
+ // Not installed due to different scheme.
+ VerifyInstallState(SearchProviderInstallData::NOT_INSTALLED,
+ "https://" + search_provider_host_ + "/");
+
+ // Not installed.
+ VerifyInstallState(SearchProviderInstallData::NOT_INSTALLED,
+ "http://a" + search_provider_host_ + "/");
+
+ // Installed as default.
+ if (!default_search_provider_host_.empty()) {
+ VerifyInstallState(SearchProviderInstallData::INSTALLED_AS_DEFAULT,
+ "http://" + default_search_provider_host_ + "/");
+ }
+
+ // All done.
+ main_loop_->PostTask(FROM_HERE, new MessageLoop::QuitTask());
+}
+
+void TestGetInstallState::VerifyInstallState(
+ SearchProviderInstallData::State expected_state,
+ const std::string& url) {
+
+ SearchProviderInstallData::State actual_state =
+ install_data_.GetInstallState(GURL(url));
+ if (expected_state == actual_state)
+ return;
+
+ passed_ = false;
+ LOG(ERROR) << "GetInstallState for " << url << " failed. Expected " <<
+ expected_state << ". Actual " << actual_state << ".";
+}
+
+// Provides basic test set-up/tear-down functionality needed by all tests
+// that use TemplateURLModelTestUtil.
+class SearchProviderInstallDataTest : public testing::Test {
+ public:
+ SearchProviderInstallDataTest() {}
+
+ virtual void SetUp() {
+ testing::Test::SetUp();
+ util_.SetUp();
+ io_thread_.reset(new ChromeThread(ChromeThread::IO));
+ io_thread_->Start();
+ }
+
+ virtual void TearDown() {
+ io_thread_->Stop();
+ io_thread_.reset();
+ util_.TearDown();
+ testing::Test::TearDown();
+ }
+
+ protected:
+ TemplateURLModelTestUtil util_;
+ scoped_ptr<ChromeThread> io_thread_;
+
+ DISALLOW_COPY_AND_ASSIGN(SearchProviderInstallDataTest);
+};
+
+TEST_F(SearchProviderInstallDataTest, GetInstallState) {
+ // Set up the database.
+ util_.ChangeModelToLoadState();
+ std::string host = "www.unittest.com";
+ TemplateURL* t_url = CreateTemplateURL("http://" + host + "/path",
+ L"unittest");
+ util_.model()->Add(t_url);
+
+ // Wait for the changes to be saved.
+ util_.BlockTillServiceProcessesRequests();
+
+ // Verify the search providers install state (with no default set).
+ scoped_refptr<TestGetInstallState> test_get_install_state(
+ new TestGetInstallState(util_.GetWebDataService()));
+ test_get_install_state->set_search_provider_host(host);
+ EXPECT_TRUE(test_get_install_state->RunTests(*io_thread_.get()));
+
+ // Set-up a default and try it all one more time.
+ std::string default_host = "www.mmm.com";
+ TemplateURL* default_url = CreateTemplateURL("http://" + default_host + "/",
+ L"mmm");
+ util_.model()->Add(default_url);
+ util_.model()->SetDefaultSearchProvider(default_url);
+ test_get_install_state->set_default_search_provider_host(default_host);
+ EXPECT_TRUE(test_get_install_state->RunTests(*io_thread_.get()));
+}
diff --git a/chrome/browser/search_engines/template_url_prepopulate_data.cc b/chrome/browser/search_engines/template_url_prepopulate_data.cc
index c542ddd..7b745bd 100644
--- a/chrome/browser/search_engines/template_url_prepopulate_data.cc
+++ b/chrome/browser/search_engines/template_url_prepopulate_data.cc
@@ -3185,6 +3185,9 @@ TemplateURL* MakePrepopulatedTemplateURL(const wchar_t* name,
void GetPrepopulatedTemplateFromPrefs(PrefService* prefs,
std::vector<TemplateURL*>* t_urls) {
+ if (!prefs)
+ return;
+
const ListValue* list =
prefs->GetList(prefs::kSearchProviderOverrides);
if (!list)
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 205b82c..ece83e9 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -2465,6 +2465,7 @@
'browser/search_engines/search_host_to_urls_map.h',
'browser/search_engines/search_host_to_urls_map.cc',
'browser/search_engines/search_provider_install_data.h',
+ 'browser/search_engines/search_provider_install_data.cc',
'browser/search_engines/search_provider_install_state_dispatcher_host.cc',
'browser/search_engines/search_provider_install_state_dispatcher_host.h',
'browser/search_engines/search_terms_data.cc',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 9ce7667..d7f34dc 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1216,6 +1216,7 @@
'browser/safe_browsing/safe_browsing_util_unittest.cc',
'browser/search_engines/keyword_editor_controller_unittest.cc',
'browser/search_engines/search_host_to_urls_map_unittest.cc',
+ 'browser/search_engines/search_provider_install_data_unittest.cc',
'browser/search_engines/template_url_model_test_util.cc',
'browser/search_engines/template_url_model_test_util.h',
'browser/search_engines/template_url_model_unittest.cc',