1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/search_engines/search_host_to_urls_map.h"
6
7#include "base/memory/scoped_ptr.h"
8#include "base/task.h"
9#include "chrome/browser/search_engines/template_url.h"
10#include "chrome/browser/search_engines/template_url_model.h"
11
12SearchHostToURLsMap::SearchHostToURLsMap()
13    : initialized_(false) {
14}
15
16SearchHostToURLsMap::~SearchHostToURLsMap() {
17}
18
19void SearchHostToURLsMap::Init(
20    const std::vector<const TemplateURL*>& template_urls,
21    const SearchTermsData& search_terms_data) {
22  DCHECK(!initialized_);
23
24  // Set as initialized here so Add doesn't assert.
25  initialized_ = true;
26
27  for (size_t i = 0; i < template_urls.size(); ++i)
28    Add(template_urls[i], search_terms_data);
29}
30
31void SearchHostToURLsMap::Add(const TemplateURL* template_url,
32                              const SearchTermsData& search_terms_data) {
33  DCHECK(initialized_);
34  DCHECK(template_url);
35
36  const GURL url(TemplateURLModel::GenerateSearchURLUsingTermsData(
37      template_url, search_terms_data));
38  if (!url.is_valid() || !url.has_host())
39    return;
40
41  host_to_urls_map_[url.host()].insert(template_url);
42}
43
44void SearchHostToURLsMap::Remove(const TemplateURL* template_url) {
45  DCHECK(initialized_);
46  DCHECK(template_url);
47
48  const GURL url(TemplateURLModel::GenerateSearchURL(template_url));
49  if (!url.is_valid() || !url.has_host())
50    return;
51
52  const std::string host(url.host());
53  DCHECK(host_to_urls_map_.find(host) != host_to_urls_map_.end());
54
55  TemplateURLSet& urls = host_to_urls_map_[host];
56  DCHECK(urls.find(template_url) != urls.end());
57
58  urls.erase(urls.find(template_url));
59  if (urls.empty())
60    host_to_urls_map_.erase(host_to_urls_map_.find(host));
61}
62
63void SearchHostToURLsMap::Update(const TemplateURL* existing_turl,
64                                 const TemplateURL& new_values,
65                                 const SearchTermsData& search_terms_data) {
66  DCHECK(initialized_);
67  DCHECK(existing_turl);
68
69  Remove(existing_turl);
70
71  // Use the information from new_values but preserve existing_turl's id.
72  TemplateURLID previous_id = existing_turl->id();
73  TemplateURL* modifiable_turl = const_cast<TemplateURL*>(existing_turl);
74  *modifiable_turl = new_values;
75  modifiable_turl->set_id(previous_id);
76
77  Add(existing_turl, search_terms_data);
78}
79
80void SearchHostToURLsMap::UpdateGoogleBaseURLs(
81    const SearchTermsData& search_terms_data) {
82  DCHECK(initialized_);
83
84  // Create a list of the the TemplateURLs to update.
85  std::vector<const TemplateURL*> t_urls_using_base_url;
86  for (HostToURLsMap::iterator host_map_iterator = host_to_urls_map_.begin();
87       host_map_iterator != host_to_urls_map_.end(); ++host_map_iterator) {
88    const TemplateURLSet& urls = host_map_iterator->second;
89    for (TemplateURLSet::const_iterator url_set_iterator = urls.begin();
90         url_set_iterator != urls.end(); ++url_set_iterator) {
91      const TemplateURL* t_url = *url_set_iterator;
92      if ((t_url->url() && t_url->url()->HasGoogleBaseURLs()) ||
93          (t_url->suggestions_url() &&
94           t_url->suggestions_url()->HasGoogleBaseURLs())) {
95        t_urls_using_base_url.push_back(t_url);
96      }
97    }
98  }
99
100  for (size_t i = 0; i < t_urls_using_base_url.size(); ++i)
101    RemoveByPointer(t_urls_using_base_url[i]);
102
103  for (size_t i = 0; i < t_urls_using_base_url.size(); ++i)
104    Add(t_urls_using_base_url[i], search_terms_data);
105}
106
107const TemplateURL* SearchHostToURLsMap::GetTemplateURLForHost(
108    const std::string& host) const {
109  DCHECK(initialized_);
110
111  HostToURLsMap::const_iterator iter = host_to_urls_map_.find(host);
112  if (iter == host_to_urls_map_.end() || iter->second.empty())
113    return NULL;
114  return *(iter->second.begin());  // Return the 1st element.
115}
116
117const SearchHostToURLsMap::TemplateURLSet* SearchHostToURLsMap::GetURLsForHost(
118    const std::string& host) const {
119  DCHECK(initialized_);
120
121  HostToURLsMap::const_iterator urls_for_host = host_to_urls_map_.find(host);
122  if (urls_for_host == host_to_urls_map_.end() || urls_for_host->second.empty())
123    return NULL;
124  return &urls_for_host->second;
125}
126
127void SearchHostToURLsMap::RemoveByPointer(
128    const TemplateURL* template_url) {
129  for (HostToURLsMap::iterator i = host_to_urls_map_.begin();
130       i != host_to_urls_map_.end(); ++i) {
131    TemplateURLSet::iterator url_set_iterator = i->second.find(template_url);
132    if (url_set_iterator != i->second.end()) {
133      i->second.erase(url_set_iterator);
134      if (i->second.empty())
135        host_to_urls_map_.erase(i);
136      // A given TemplateURL only occurs once in the map. As soon as we find the
137      // entry, stop.
138      return;
139    }
140  }
141}
142