Componentize ShortcutsBackend
[chromium-blink-merge.git] / chrome / browser / search_engines / search_provider_install_data.cc
blobfdb0fcdb22b1d220c0d1de51f8ff003f21fee1bd
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
3 // found in the LICENSE file.
5 #include "chrome/browser/search_engines/search_provider_install_data.h"
7 #include <algorithm>
8 #include <functional>
9 #include <vector>
11 #include "base/basictypes.h"
12 #include "base/bind.h"
13 #include "base/bind_helpers.h"
14 #include "base/logging.h"
15 #include "base/memory/ref_counted.h"
16 #include "base/sequenced_task_runner_helpers.h"
17 #include "components/google/core/browser/google_url_tracker.h"
18 #include "components/search_engines/search_host_to_urls_map.h"
19 #include "components/search_engines/search_terms_data.h"
20 #include "components/search_engines/template_url.h"
21 #include "components/search_engines/template_url_service.h"
22 #include "components/search_engines/util.h"
23 #include "content/public/browser/browser_thread.h"
24 #include "content/public/browser/render_process_host.h"
25 #include "content/public/browser/render_process_host_observer.h"
27 using content::BrowserThread;
29 typedef SearchHostToURLsMap::TemplateURLSet TemplateURLSet;
31 namespace {
33 void LoadDataOnUIThread(TemplateURLService* template_url_service,
34 const base::Callback<void(ScopedVector<TemplateURL>,
35 TemplateURL*)>& callback) {
36 ScopedVector<TemplateURL> template_url_copies;
37 TemplateURL* default_provider_copy = NULL;
38 TemplateURLService::TemplateURLVector original_template_urls =
39 template_url_service->GetTemplateURLs();
40 TemplateURL* original_default_provider =
41 template_url_service->GetDefaultSearchProvider();
42 for (TemplateURLService::TemplateURLVector::const_iterator it =
43 original_template_urls.begin();
44 it != original_template_urls.end();
45 ++it) {
46 template_url_copies.push_back(new TemplateURL((*it)->data()));
47 if (*it == original_default_provider)
48 default_provider_copy = template_url_copies.back();
50 BrowserThread::PostTask(BrowserThread::IO,
51 FROM_HERE,
52 base::Bind(callback,
53 base::Passed(template_url_copies.Pass()),
54 base::Unretained(default_provider_copy)));
57 // Implementation of SearchTermsData that may be used on the I/O thread.
58 class IOThreadSearchTermsData : public SearchTermsData {
59 public:
60 explicit IOThreadSearchTermsData(const std::string& google_base_url);
62 // Implementation of SearchTermsData.
63 std::string GoogleBaseURLValue() const override;
65 private:
66 std::string google_base_url_;
68 DISALLOW_COPY_AND_ASSIGN(IOThreadSearchTermsData);
71 IOThreadSearchTermsData::IOThreadSearchTermsData(
72 const std::string& google_base_url) : google_base_url_(google_base_url) {
75 std::string IOThreadSearchTermsData::GoogleBaseURLValue() const {
76 return google_base_url_;
79 // Handles telling SearchProviderInstallData about changes to the google base
80 // url. (Ensure that this is deleted on the I/O thread so that the WeakPtr is
81 // deleted on the correct thread.)
82 class GoogleURLChangeNotifier
83 : public base::RefCountedThreadSafe<GoogleURLChangeNotifier,
84 BrowserThread::DeleteOnIOThread> {
85 public:
86 explicit GoogleURLChangeNotifier(
87 const base::WeakPtr<SearchProviderInstallData>& install_data);
89 // Called on the I/O thread with the Google base URL whenever the value
90 // changes.
91 void OnChange(const std::string& google_base_url);
93 private:
94 friend struct BrowserThread::DeleteOnThread<BrowserThread::IO>;
95 friend class base::DeleteHelper<GoogleURLChangeNotifier>;
97 ~GoogleURLChangeNotifier() {}
99 base::WeakPtr<SearchProviderInstallData> install_data_;
101 DISALLOW_COPY_AND_ASSIGN(GoogleURLChangeNotifier);
104 GoogleURLChangeNotifier::GoogleURLChangeNotifier(
105 const base::WeakPtr<SearchProviderInstallData>& install_data)
106 : install_data_(install_data) {
109 void GoogleURLChangeNotifier::OnChange(const std::string& google_base_url) {
110 DCHECK_CURRENTLY_ON(BrowserThread::IO);
111 if (install_data_.get())
112 install_data_->OnGoogleURLChange(google_base_url);
115 // Notices changes in the Google base URL and sends them along
116 // to the SearchProviderInstallData on the I/O thread.
117 class GoogleURLObserver : public content::RenderProcessHostObserver {
118 public:
119 GoogleURLObserver(GoogleURLTracker* google_url_tracker,
120 GoogleURLChangeNotifier* change_notifier,
121 content::RenderProcessHost* host);
123 // Implementation of content::RenderProcessHostObserver.
124 void RenderProcessHostDestroyed(content::RenderProcessHost* host) override;
126 private:
127 ~GoogleURLObserver() override {}
129 // Callback that is called when the Google URL is updated.
130 void OnGoogleURLUpdated();
132 GoogleURLTracker* google_url_tracker_;
133 scoped_refptr<GoogleURLChangeNotifier> change_notifier_;
135 scoped_ptr<GoogleURLTracker::Subscription> google_url_updated_subscription_;
137 DISALLOW_COPY_AND_ASSIGN(GoogleURLObserver);
140 GoogleURLObserver::GoogleURLObserver(
141 GoogleURLTracker* google_url_tracker,
142 GoogleURLChangeNotifier* change_notifier,
143 content::RenderProcessHost* host)
144 : google_url_tracker_(google_url_tracker),
145 change_notifier_(change_notifier) {
146 DCHECK_CURRENTLY_ON(BrowserThread::UI);
147 google_url_updated_subscription_ =
148 google_url_tracker_->RegisterCallback(base::Bind(
149 &GoogleURLObserver::OnGoogleURLUpdated, base::Unretained(this)));
150 host->AddObserver(this);
153 void GoogleURLObserver::OnGoogleURLUpdated() {
154 BrowserThread::PostTask(BrowserThread::IO,
155 FROM_HERE,
156 base::Bind(&GoogleURLChangeNotifier::OnChange,
157 change_notifier_.get(),
158 google_url_tracker_->google_url().spec()));
161 void GoogleURLObserver::RenderProcessHostDestroyed(
162 content::RenderProcessHost* host) {
163 delete this;
166 // Indicates if the two inputs have the same security origin.
167 // |requested_origin| should only be a security origin (no path, etc.).
168 // It is ok if |template_url| is NULL.
169 static bool IsSameOrigin(const GURL& requested_origin,
170 TemplateURL* template_url,
171 const SearchTermsData& search_terms_data) {
172 DCHECK(requested_origin == requested_origin.GetOrigin());
173 DCHECK(template_url->GetType() != TemplateURL::OMNIBOX_API_EXTENSION);
174 return requested_origin ==
175 template_url->GenerateSearchURL(search_terms_data).GetOrigin();
178 } // namespace
180 SearchProviderInstallData::SearchProviderInstallData(
181 TemplateURLService* template_url_service,
182 const std::string& google_base_url,
183 GoogleURLTracker* google_url_tracker,
184 content::RenderProcessHost* host)
185 : template_url_service_(template_url_service),
186 google_base_url_(google_base_url),
187 weak_factory_(this) {
188 // GoogleURLTracker is not created in tests.
189 if (google_url_tracker) {
190 // GoogleURLObserver is responsible for killing itself when
191 // the given notification occurs.
192 new GoogleURLObserver(
193 google_url_tracker,
194 new GoogleURLChangeNotifier(weak_factory_.GetWeakPtr()),
195 host);
199 SearchProviderInstallData::~SearchProviderInstallData() {
200 DCHECK_CURRENTLY_ON(BrowserThread::IO);
203 void SearchProviderInstallData::CallWhenLoaded(const base::Closure& closure) {
204 DCHECK_CURRENTLY_ON(BrowserThread::IO);
206 if (provider_map_.get()) {
207 closure.Run();
208 return;
211 bool do_load = closure_queue_.empty();
212 closure_queue_.push_back(closure);
214 // If the queue wasn't empty, there was already a load in progress.
215 if (!do_load)
216 return;
218 if (template_url_service_) {
219 BrowserThread::PostTask(
220 BrowserThread::UI,
221 FROM_HERE,
222 base::Bind(&LoadDataOnUIThread,
223 template_url_service_,
224 base::Bind(&SearchProviderInstallData::OnTemplateURLsLoaded,
225 weak_factory_.GetWeakPtr())));
226 } else {
227 OnLoadFailed();
231 SearchProviderInstallData::State SearchProviderInstallData::GetInstallState(
232 const GURL& requested_origin) {
233 DCHECK_CURRENTLY_ON(BrowserThread::IO);
234 DCHECK(provider_map_.get());
236 // First check to see if the origin is the default search provider.
237 if (requested_origin.spec() == default_search_origin_)
238 return INSTALLED_AS_DEFAULT;
240 // Is the url any search provider?
241 const TemplateURLSet* urls = provider_map_->GetURLsForHost(
242 requested_origin.host());
243 if (!urls)
244 return NOT_INSTALLED;
246 IOThreadSearchTermsData search_terms_data(google_base_url_);
247 for (TemplateURLSet::const_iterator i = urls->begin();
248 i != urls->end(); ++i) {
249 if (IsSameOrigin(requested_origin, *i, search_terms_data))
250 return INSTALLED_BUT_NOT_DEFAULT;
252 return NOT_INSTALLED;
255 void SearchProviderInstallData::OnGoogleURLChange(
256 const std::string& google_base_url) {
257 google_base_url_ = google_base_url;
260 void SearchProviderInstallData::OnTemplateURLsLoaded(
261 ScopedVector<TemplateURL> template_urls,
262 TemplateURL* default_provider) {
263 DCHECK_CURRENTLY_ON(BrowserThread::IO);
265 template_urls_ = template_urls.Pass();
267 IOThreadSearchTermsData search_terms_data(google_base_url_);
268 provider_map_.reset(new SearchHostToURLsMap());
269 provider_map_->Init(template_urls_.get(), search_terms_data);
270 SetDefault(default_provider);
271 NotifyLoaded();
274 void SearchProviderInstallData::SetDefault(const TemplateURL* template_url) {
275 DCHECK_CURRENTLY_ON(BrowserThread::IO);
277 if (!template_url) {
278 default_search_origin_.clear();
279 return;
282 DCHECK(template_url->GetType() != TemplateURL::OMNIBOX_API_EXTENSION);
284 IOThreadSearchTermsData search_terms_data(google_base_url_);
285 const GURL url(template_url->GenerateSearchURL(search_terms_data));
286 if (!url.is_valid() || !url.has_host()) {
287 default_search_origin_.clear();
288 return;
290 default_search_origin_ = url.GetOrigin().spec();
293 void SearchProviderInstallData::OnLoadFailed() {
294 DCHECK_CURRENTLY_ON(BrowserThread::IO);
296 provider_map_.reset(new SearchHostToURLsMap());
297 IOThreadSearchTermsData search_terms_data(google_base_url_);
298 provider_map_->Init(template_urls_.get(), search_terms_data);
299 SetDefault(NULL);
300 NotifyLoaded();
303 void SearchProviderInstallData::NotifyLoaded() {
304 DCHECK_CURRENTLY_ON(BrowserThread::IO);
306 std::vector<base::Closure> closure_queue;
307 closure_queue.swap(closure_queue_);
309 std::for_each(closure_queue.begin(),
310 closure_queue.end(),
311 std::mem_fun_ref(&base::Closure::Run));
313 // Since we expect this request to be rare, clear out the information. This
314 // also keeps the responses current as the search providers change.
315 provider_map_.reset();
316 SetDefault(NULL);