Temporarily re-enabling SizeAfterPrefChange test with traces (this time for Linux...
[chromium-blink-merge.git] / chrome / browser / search_engines / search_provider_install_data.cc
blob0f52fd06ed5054563641ac7ffc73e735c08af010
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 "chrome/browser/chrome_notification_types.h"
18 #include "chrome/browser/google/google_url_tracker.h"
19 #include "chrome/browser/google/google_url_tracker_factory.h"
20 #include "chrome/browser/profiles/profile.h"
21 #include "chrome/browser/search_engines/search_host_to_urls_map.h"
22 #include "chrome/browser/search_engines/search_terms_data.h"
23 #include "chrome/browser/search_engines/template_url.h"
24 #include "chrome/browser/search_engines/template_url_service.h"
25 #include "chrome/browser/search_engines/template_url_service_factory.h"
26 #include "chrome/browser/search_engines/util.h"
27 #include "chrome/browser/webdata/web_data_service.h"
28 #include "content/public/browser/browser_thread.h"
29 #include "content/public/browser/render_process_host.h"
30 #include "content/public/browser/render_process_host_observer.h"
32 using content::BrowserThread;
34 typedef SearchHostToURLsMap::TemplateURLSet TemplateURLSet;
36 namespace {
38 void LoadDataOnUIThread(TemplateURLService* template_url_service,
39 const base::Callback<void(ScopedVector<TemplateURL>,
40 TemplateURL*)>& callback) {
41 ScopedVector<TemplateURL> template_url_copies;
42 TemplateURL* default_provider_copy = NULL;
43 TemplateURLService::TemplateURLVector original_template_urls =
44 template_url_service->GetTemplateURLs();
45 TemplateURL* original_default_provider =
46 template_url_service->GetDefaultSearchProvider();
47 for (TemplateURLService::TemplateURLVector::const_iterator it =
48 original_template_urls.begin();
49 it != original_template_urls.end();
50 ++it) {
51 template_url_copies.push_back(new TemplateURL(NULL, (*it)->data()));
52 if (*it == original_default_provider)
53 default_provider_copy = template_url_copies.back();
55 BrowserThread::PostTask(BrowserThread::IO,
56 FROM_HERE,
57 base::Bind(callback,
58 base::Passed(template_url_copies.Pass()),
59 base::Unretained(default_provider_copy)));
62 // Implementation of SearchTermsData that may be used on the I/O thread.
63 class IOThreadSearchTermsData : public SearchTermsData {
64 public:
65 explicit IOThreadSearchTermsData(const std::string& google_base_url);
67 // Implementation of SearchTermsData.
68 virtual std::string GoogleBaseURLValue() const OVERRIDE;
70 private:
71 std::string google_base_url_;
73 DISALLOW_COPY_AND_ASSIGN(IOThreadSearchTermsData);
76 IOThreadSearchTermsData::IOThreadSearchTermsData(
77 const std::string& google_base_url) : google_base_url_(google_base_url) {
80 std::string IOThreadSearchTermsData::GoogleBaseURLValue() const {
81 return google_base_url_;
84 // Handles telling SearchProviderInstallData about changes to the google base
85 // url. (Ensure that this is deleted on the I/O thread so that the WeakPtr is
86 // deleted on the correct thread.)
87 class GoogleURLChangeNotifier
88 : public base::RefCountedThreadSafe<GoogleURLChangeNotifier,
89 BrowserThread::DeleteOnIOThread> {
90 public:
91 explicit GoogleURLChangeNotifier(
92 const base::WeakPtr<SearchProviderInstallData>& install_data);
94 // Called on the I/O thread with the Google base URL whenever the value
95 // changes.
96 void OnChange(const std::string& google_base_url);
98 private:
99 friend struct BrowserThread::DeleteOnThread<BrowserThread::IO>;
100 friend class base::DeleteHelper<GoogleURLChangeNotifier>;
102 ~GoogleURLChangeNotifier() {}
104 base::WeakPtr<SearchProviderInstallData> install_data_;
106 DISALLOW_COPY_AND_ASSIGN(GoogleURLChangeNotifier);
109 GoogleURLChangeNotifier::GoogleURLChangeNotifier(
110 const base::WeakPtr<SearchProviderInstallData>& install_data)
111 : install_data_(install_data) {
114 void GoogleURLChangeNotifier::OnChange(const std::string& google_base_url) {
115 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
116 if (install_data_.get())
117 install_data_->OnGoogleURLChange(google_base_url);
120 // Notices changes in the Google base URL and sends them along
121 // to the SearchProviderInstallData on the I/O thread.
122 class GoogleURLObserver : public content::RenderProcessHostObserver {
123 public:
124 GoogleURLObserver(Profile* profile,
125 GoogleURLChangeNotifier* change_notifier,
126 content::RenderProcessHost* host);
128 // Implementation of content::RenderProcessHostObserver.
129 virtual void RenderProcessHostDestroyed(
130 content::RenderProcessHost* host) OVERRIDE;
132 private:
133 virtual ~GoogleURLObserver() {}
135 // Callback that is called when the Google URL is updated.
136 void OnGoogleURLUpdated(GURL old_url, GURL new_url);
138 scoped_refptr<GoogleURLChangeNotifier> change_notifier_;
140 scoped_ptr<GoogleURLTracker::Subscription> google_url_updated_subscription_;
142 DISALLOW_COPY_AND_ASSIGN(GoogleURLObserver);
145 GoogleURLObserver::GoogleURLObserver(
146 Profile* profile,
147 GoogleURLChangeNotifier* change_notifier,
148 content::RenderProcessHost* host)
149 : change_notifier_(change_notifier) {
150 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
151 GoogleURLTracker* google_url_tracker =
152 GoogleURLTrackerFactory::GetForProfile(profile);
154 // GoogleURLTracker is not created in tests.
155 if (google_url_tracker) {
156 google_url_updated_subscription_ =
157 google_url_tracker->RegisterCallback(base::Bind(
158 &GoogleURLObserver::OnGoogleURLUpdated, base::Unretained(this)));
160 host->AddObserver(this);
163 void GoogleURLObserver::OnGoogleURLUpdated(GURL old_url, GURL new_url) {
164 BrowserThread::PostTask(BrowserThread::IO,
165 FROM_HERE,
166 base::Bind(&GoogleURLChangeNotifier::OnChange,
167 change_notifier_.get(),
168 new_url.spec()));
171 void GoogleURLObserver::RenderProcessHostDestroyed(
172 content::RenderProcessHost* host) {
173 delete this;
176 // Indicates if the two inputs have the same security origin.
177 // |requested_origin| should only be a security origin (no path, etc.).
178 // It is ok if |template_url| is NULL.
179 static bool IsSameOrigin(const GURL& requested_origin,
180 TemplateURL* template_url,
181 const SearchTermsData& search_terms_data) {
182 DCHECK(requested_origin == requested_origin.GetOrigin());
183 DCHECK(template_url->GetType() != TemplateURL::OMNIBOX_API_EXTENSION);
184 return requested_origin ==
185 TemplateURLService::GenerateSearchURLUsingTermsData(template_url,
186 search_terms_data).GetOrigin();
189 } // namespace
191 SearchProviderInstallData::SearchProviderInstallData(
192 Profile* profile,
193 content::RenderProcessHost* host)
194 : template_url_service_(TemplateURLServiceFactory::GetForProfile(profile)),
195 google_base_url_(UIThreadSearchTermsData(profile).GoogleBaseURLValue()),
196 weak_factory_(this) {
197 // GoogleURLObserver is responsible for killing itself when
198 // the given notification occurs.
199 new GoogleURLObserver(profile,
200 new GoogleURLChangeNotifier(weak_factory_.GetWeakPtr()),
201 host);
204 SearchProviderInstallData::~SearchProviderInstallData() {
205 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
208 void SearchProviderInstallData::CallWhenLoaded(const base::Closure& closure) {
209 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
211 if (provider_map_.get()) {
212 closure.Run();
213 return;
216 bool do_load = closure_queue_.empty();
217 closure_queue_.push_back(closure);
219 // If the queue wasn't empty, there was already a load in progress.
220 if (!do_load)
221 return;
223 if (template_url_service_) {
224 BrowserThread::PostTask(
225 BrowserThread::UI,
226 FROM_HERE,
227 base::Bind(&LoadDataOnUIThread,
228 template_url_service_,
229 base::Bind(&SearchProviderInstallData::OnTemplateURLsLoaded,
230 weak_factory_.GetWeakPtr())));
231 } else {
232 OnLoadFailed();
236 SearchProviderInstallData::State SearchProviderInstallData::GetInstallState(
237 const GURL& requested_origin) {
238 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
239 DCHECK(provider_map_.get());
241 // First check to see if the origin is the default search provider.
242 if (requested_origin.spec() == default_search_origin_)
243 return INSTALLED_AS_DEFAULT;
245 // Is the url any search provider?
246 const TemplateURLSet* urls = provider_map_->GetURLsForHost(
247 requested_origin.host());
248 if (!urls)
249 return NOT_INSTALLED;
251 IOThreadSearchTermsData search_terms_data(google_base_url_);
252 for (TemplateURLSet::const_iterator i = urls->begin();
253 i != urls->end(); ++i) {
254 if (IsSameOrigin(requested_origin, *i, search_terms_data))
255 return INSTALLED_BUT_NOT_DEFAULT;
257 return NOT_INSTALLED;
260 void SearchProviderInstallData::OnGoogleURLChange(
261 const std::string& google_base_url) {
262 google_base_url_ = google_base_url;
265 void SearchProviderInstallData::OnTemplateURLsLoaded(
266 ScopedVector<TemplateURL> template_urls,
267 TemplateURL* default_provider) {
268 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
270 template_urls_ = template_urls.Pass();
272 IOThreadSearchTermsData search_terms_data(google_base_url_);
273 provider_map_.reset(new SearchHostToURLsMap());
274 provider_map_->Init(template_urls_.get(), search_terms_data);
275 SetDefault(default_provider);
276 NotifyLoaded();
279 void SearchProviderInstallData::SetDefault(const TemplateURL* template_url) {
280 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
282 if (!template_url) {
283 default_search_origin_.clear();
284 return;
287 DCHECK(template_url->GetType() != TemplateURL::OMNIBOX_API_EXTENSION);
289 IOThreadSearchTermsData search_terms_data(google_base_url_);
290 const GURL url(TemplateURLService::GenerateSearchURLUsingTermsData(
291 template_url, search_terms_data));
292 if (!url.is_valid() || !url.has_host()) {
293 default_search_origin_.clear();
294 return;
296 default_search_origin_ = url.GetOrigin().spec();
299 void SearchProviderInstallData::OnLoadFailed() {
300 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
302 provider_map_.reset(new SearchHostToURLsMap());
303 IOThreadSearchTermsData search_terms_data(google_base_url_);
304 provider_map_->Init(template_urls_.get(), search_terms_data);
305 SetDefault(NULL);
306 NotifyLoaded();
309 void SearchProviderInstallData::NotifyLoaded() {
310 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
312 std::vector<base::Closure> closure_queue;
313 closure_queue.swap(closure_queue_);
315 std::for_each(closure_queue.begin(),
316 closure_queue.end(),
317 std::mem_fun_ref(&base::Closure::Run));
319 // Since we expect this request to be rare, clear out the information. This
320 // also keeps the responses current as the search providers change.
321 provider_map_.reset();
322 SetDefault(NULL);