Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(544)

Side by Side Diff: chrome/browser/search/instant_service.cc

Issue 272573004: Handle TemplateURLService load failure better, and make some test correctness fixes that will be ne… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase after revert / presubmit fixes. Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/search/instant_service.h" 5 #include "chrome/browser/search/instant_service.h"
6 6
7 #include <vector>
8
9 #include "base/logging.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "chrome/browser/chrome_notification_types.h" 7 #include "chrome/browser/chrome_notification_types.h"
13 #include "chrome/browser/history/history_notifications.h"
14 #include "chrome/browser/history/most_visited_tiles_experiment.h" 8 #include "chrome/browser/history/most_visited_tiles_experiment.h"
15 #include "chrome/browser/history/top_sites.h" 9 #include "chrome/browser/history/top_sites.h"
16 #include "chrome/browser/profiles/profile.h" 10 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/browser/search/instant_io_context.h" 11 #include "chrome/browser/search/instant_io_context.h"
18 #include "chrome/browser/search/instant_service_factory.h"
19 #include "chrome/browser/search/instant_service_observer.h" 12 #include "chrome/browser/search/instant_service_observer.h"
20 #include "chrome/browser/search/local_ntp_source.h" 13 #include "chrome/browser/search/local_ntp_source.h"
21 #include "chrome/browser/search/most_visited_iframe_source.h" 14 #include "chrome/browser/search/most_visited_iframe_source.h"
22 #include "chrome/browser/search/search.h" 15 #include "chrome/browser/search/search.h"
23 #include "chrome/browser/search/suggestions/suggestions_source.h" 16 #include "chrome/browser/search/suggestions/suggestions_source.h"
24 #include "chrome/browser/search_engines/template_url.h" 17 #include "chrome/browser/search_engines/search_terms_data.h"
25 #include "chrome/browser/search_engines/template_url_service.h" 18 #include "chrome/browser/search_engines/template_url_service.h"
26 #include "chrome/browser/search_engines/template_url_service_factory.h" 19 #include "chrome/browser/search_engines/template_url_service_factory.h"
27 #include "chrome/browser/themes/theme_properties.h" 20 #include "chrome/browser/themes/theme_properties.h"
28 #include "chrome/browser/themes/theme_service.h" 21 #include "chrome/browser/themes/theme_service.h"
29 #include "chrome/browser/themes/theme_service_factory.h" 22 #include "chrome/browser/themes/theme_service_factory.h"
30 #include "chrome/browser/thumbnails/thumbnail_list_source.h" 23 #include "chrome/browser/thumbnails/thumbnail_list_source.h"
24 #include "chrome/browser/ui/search/instant_search_prerenderer.h"
31 #include "chrome/browser/ui/webui/favicon_source.h" 25 #include "chrome/browser/ui/webui/favicon_source.h"
32 #include "chrome/browser/ui/webui/ntp/thumbnail_source.h" 26 #include "chrome/browser/ui/webui/ntp/thumbnail_source.h"
33 #include "chrome/browser/ui/webui/theme_source.h" 27 #include "chrome/browser/ui/webui/theme_source.h"
34 #include "chrome/common/pref_names.h"
35 #include "chrome/common/render_messages.h" 28 #include "chrome/common/render_messages.h"
36 #include "content/public/browser/browser_thread.h" 29 #include "content/public/browser/browser_thread.h"
37 #include "content/public/browser/notification_details.h"
38 #include "content/public/browser/notification_service.h" 30 #include "content/public/browser/notification_service.h"
39 #include "content/public/browser/notification_source.h"
40 #include "content/public/browser/notification_types.h" 31 #include "content/public/browser/notification_types.h"
41 #include "content/public/browser/render_process_host.h" 32 #include "content/public/browser/render_process_host.h"
42 #include "content/public/browser/url_data_source.h" 33 #include "content/public/browser/url_data_source.h"
43 #include "grit/theme_resources.h" 34 #include "grit/theme_resources.h"
44 #include "net/base/net_util.h" 35 #include "third_party/skia/include/core/SkColor.h"
45 #include "net/url_request/url_request.h"
46 #include "ui/gfx/color_utils.h" 36 #include "ui/gfx/color_utils.h"
47 #include "ui/gfx/image/image_skia.h" 37 #include "ui/gfx/image/image_skia.h"
48 #include "ui/gfx/sys_color_change_listener.h" 38 #include "ui/gfx/sys_color_change_listener.h"
49 #include "url/gurl.h"
50 39
51 using content::BrowserThread;
52 40
53 namespace { 41 namespace {
54 42
55 const int kSectionBorderAlphaTransparency = 80; 43 const int kSectionBorderAlphaTransparency = 80;
56 44
57 // Converts SkColor to RGBAColor 45 // Converts SkColor to RGBAColor
58 RGBAColor SkColorToRGBAColor(const SkColor& sKColor) { 46 RGBAColor SkColorToRGBAColor(const SkColor& sKColor) {
59 RGBAColor color; 47 RGBAColor color;
60 color.r = SkColorGetR(sKColor); 48 color.r = SkColorGetR(sKColor);
61 color.g = SkColorGetG(sKColor); 49 color.g = SkColorGetG(sKColor);
62 color.b = SkColorGetB(sKColor); 50 color.b = SkColorGetB(sKColor);
63 color.a = SkColorGetA(sKColor); 51 color.a = SkColorGetA(sKColor);
64 return color; 52 return color;
65 } 53 }
66 54
67 } // namespace 55 } // namespace
68 56
69 InstantService::InstantService(Profile* profile) 57 InstantService::InstantService(Profile* profile)
70 : profile_(profile), 58 : profile_(profile),
59 template_url_service_(TemplateURLServiceFactory::GetForProfile(profile_)),
71 omnibox_start_margin_(chrome::kDisableStartMargin), 60 omnibox_start_margin_(chrome::kDisableStartMargin),
72 weak_ptr_factory_(this) { 61 weak_ptr_factory_(this) {
73 // Stub for unit tests. 62 // The initialization below depends on a typical set of browser threads. Skip
74 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) 63 // it if we are running in a unit test without the full suite.
64 if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI))
75 return; 65 return;
76 66
67 // This depends on the existence of the typical browser threads. Therefore it
68 // is only instantiated here (after the check for a UI thread above).
69 instant_io_context_ = new InstantIOContext();
70
71 previous_google_base_url_ =
72 GURL(UIThreadSearchTermsData(profile).GoogleBaseURLValue());
73
74 // TemplateURLService is NULL by default in tests.
75 if (template_url_service_) {
76 template_url_service_->AddObserver(this);
77 const TemplateURL* default_search_provider =
78 template_url_service_->GetDefaultSearchProvider();
79 if (default_search_provider) {
80 previous_default_search_provider_.reset(
81 new TemplateURLData(default_search_provider->data()));
82 }
83 }
84
77 ResetInstantSearchPrerenderer(); 85 ResetInstantSearchPrerenderer();
78 86
79 registrar_.Add(this, 87 registrar_.Add(this,
80 content::NOTIFICATION_RENDERER_PROCESS_CREATED, 88 content::NOTIFICATION_RENDERER_PROCESS_CREATED,
81 content::NotificationService::AllSources()); 89 content::NotificationService::AllSources());
82 registrar_.Add(this, 90 registrar_.Add(this,
83 content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, 91 content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
84 content::NotificationService::AllSources()); 92 content::NotificationService::AllSources());
85 93
86 history::TopSites* top_sites = profile_->GetTopSites(); 94 history::TopSites* top_sites = profile_->GetTopSites();
87 if (top_sites) { 95 if (top_sites) {
88 registrar_.Add(this, 96 registrar_.Add(this,
89 chrome::NOTIFICATION_TOP_SITES_CHANGED, 97 chrome::NOTIFICATION_TOP_SITES_CHANGED,
90 content::Source<history::TopSites>(top_sites)); 98 content::Source<history::TopSites>(top_sites));
91 } 99 }
92 instant_io_context_ = new InstantIOContext();
93 100
94 if (profile_ && profile_->GetResourceContext()) { 101 if (profile_ && profile_->GetResourceContext()) {
95 BrowserThread::PostTask( 102 content::BrowserThread::PostTask(
96 BrowserThread::IO, FROM_HERE, 103 content::BrowserThread::IO, FROM_HERE,
97 base::Bind(&InstantIOContext::SetUserDataOnIO, 104 base::Bind(&InstantIOContext::SetUserDataOnIO,
98 profile->GetResourceContext(), instant_io_context_)); 105 profile->GetResourceContext(), instant_io_context_));
99 } 106 }
100 107
101 // Set up the data sources that Instant uses on the NTP. 108 // Set up the data sources that Instant uses on the NTP.
102 #if defined(ENABLE_THEMES) 109 #if defined(ENABLE_THEMES)
103 // Listen for theme installation. 110 // Listen for theme installation.
104 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED, 111 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
105 content::Source<ThemeService>( 112 content::Source<ThemeService>(
106 ThemeServiceFactory::GetForProfile(profile_))); 113 ThemeServiceFactory::GetForProfile(profile_)));
107 114
108 content::URLDataSource::Add(profile_, new ThemeSource(profile_)); 115 content::URLDataSource::Add(profile_, new ThemeSource(profile_));
109 #endif // defined(ENABLE_THEMES) 116 #endif // defined(ENABLE_THEMES)
110 117
111 // TODO(aurimas) remove this #if once instant_service.cc is no longer compiled 118 // TODO(aurimas) remove this #if once instant_service.cc is no longer compiled
112 // on Android. 119 // on Android.
113 #if !defined(OS_ANDROID) 120 #if !defined(OS_ANDROID)
114 content::URLDataSource::Add(profile_, new ThumbnailSource(profile_, false)); 121 content::URLDataSource::Add(profile_, new ThumbnailSource(profile_, false));
115 content::URLDataSource::Add(profile_, new ThumbnailSource(profile_, true)); 122 content::URLDataSource::Add(profile_, new ThumbnailSource(profile_, true));
116 content::URLDataSource::Add(profile_, new ThumbnailListSource(profile_)); 123 content::URLDataSource::Add(profile_, new ThumbnailListSource(profile_));
117 #endif // !defined(OS_ANDROID) 124 #endif // !defined(OS_ANDROID)
118 125
119 content::URLDataSource::Add( 126 content::URLDataSource::Add(
120 profile_, new FaviconSource(profile_, FaviconSource::FAVICON)); 127 profile_, new FaviconSource(profile_, FaviconSource::FAVICON));
121 content::URLDataSource::Add(profile_, new LocalNtpSource(profile_)); 128 content::URLDataSource::Add(profile_, new LocalNtpSource(profile_));
122 content::URLDataSource::Add(profile_, new MostVisitedIframeSource()); 129 content::URLDataSource::Add(profile_, new MostVisitedIframeSource());
123 content::URLDataSource::Add( 130 content::URLDataSource::Add(
124 profile_, new suggestions::SuggestionsSource(profile_)); 131 profile_, new suggestions::SuggestionsSource(profile_));
125
126 profile_pref_registrar_.Init(profile_->GetPrefs());
127 profile_pref_registrar_.Add(
128 prefs::kDefaultSearchProviderID,
129 base::Bind(&InstantService::OnDefaultSearchProviderChanged,
130 base::Unretained(this)));
131
132 registrar_.Add(this, chrome::NOTIFICATION_GOOGLE_URL_UPDATED,
133 content::Source<Profile>(profile_->GetOriginalProfile()));
134 } 132 }
135 133
136 InstantService::~InstantService() { 134 InstantService::~InstantService() {
135 if (template_url_service_)
136 template_url_service_->RemoveObserver(this);
137 } 137 }
138 138
139 void InstantService::AddInstantProcess(int process_id) { 139 void InstantService::AddInstantProcess(int process_id) {
140 process_ids_.insert(process_id); 140 process_ids_.insert(process_id);
141 141
142 if (instant_io_context_.get()) { 142 if (instant_io_context_.get()) {
143 BrowserThread::PostTask(BrowserThread::IO, 143 content::BrowserThread::PostTask(
144 FROM_HERE, 144 content::BrowserThread::IO, FROM_HERE,
145 base::Bind(&InstantIOContext::AddInstantProcessOnIO, 145 base::Bind(&InstantIOContext::AddInstantProcessOnIO,
146 instant_io_context_, 146 instant_io_context_, process_id));
147 process_id));
148 } 147 }
149 } 148 }
150 149
151 bool InstantService::IsInstantProcess(int process_id) const { 150 bool InstantService::IsInstantProcess(int process_id) const {
152 return process_ids_.find(process_id) != process_ids_.end(); 151 return process_ids_.find(process_id) != process_ids_.end();
153 } 152 }
154 153
155 void InstantService::AddObserver(InstantServiceObserver* observer) { 154 void InstantService::AddObserver(InstantServiceObserver* observer) {
156 observers_.AddObserver(observer); 155 observers_.AddObserver(observer);
157 } 156 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
194 } 193 }
195 194
196 void InstantService::UpdateMostVisitedItemsInfo() { 195 void InstantService::UpdateMostVisitedItemsInfo() {
197 NotifyAboutMostVisitedItems(); 196 NotifyAboutMostVisitedItems();
198 } 197 }
199 198
200 void InstantService::Shutdown() { 199 void InstantService::Shutdown() {
201 process_ids_.clear(); 200 process_ids_.clear();
202 201
203 if (instant_io_context_.get()) { 202 if (instant_io_context_.get()) {
204 BrowserThread::PostTask( 203 content::BrowserThread::PostTask(
205 BrowserThread::IO, 204 content::BrowserThread::IO, FROM_HERE,
206 FROM_HERE,
207 base::Bind(&InstantIOContext::ClearInstantProcessesOnIO, 205 base::Bind(&InstantIOContext::ClearInstantProcessesOnIO,
208 instant_io_context_)); 206 instant_io_context_));
209 } 207 }
210 instant_io_context_ = NULL; 208 instant_io_context_ = NULL;
211 } 209 }
212 210
213 void InstantService::Observe(int type, 211 void InstantService::Observe(int type,
214 const content::NotificationSource& source, 212 const content::NotificationSource& source,
215 const content::NotificationDetails& details) { 213 const content::NotificationDetails& details) {
216 switch (type) { 214 switch (type) {
(...skipping 13 matching lines...) Expand all
230 weak_ptr_factory_.GetWeakPtr()), false); 228 weak_ptr_factory_.GetWeakPtr()), false);
231 } 229 }
232 break; 230 break;
233 } 231 }
234 #if defined(ENABLE_THEMES) 232 #if defined(ENABLE_THEMES)
235 case chrome::NOTIFICATION_BROWSER_THEME_CHANGED: { 233 case chrome::NOTIFICATION_BROWSER_THEME_CHANGED: {
236 OnThemeChanged(content::Source<ThemeService>(source).ptr()); 234 OnThemeChanged(content::Source<ThemeService>(source).ptr());
237 break; 235 break;
238 } 236 }
239 #endif // defined(ENABLE_THEMES) 237 #endif // defined(ENABLE_THEMES)
240 case chrome::NOTIFICATION_GOOGLE_URL_UPDATED: {
241 OnGoogleURLUpdated(
242 content::Source<Profile>(source).ptr(),
243 content::Details<GoogleURLTracker::UpdatedDetails>(details).ptr());
244 break;
245 }
246 default: 238 default:
247 NOTREACHED() << "Unexpected notification type in InstantService."; 239 NOTREACHED() << "Unexpected notification type in InstantService.";
248 } 240 }
249 } 241 }
250 242
251 void InstantService::SendSearchURLsToRenderer(content::RenderProcessHost* rph) { 243 void InstantService::SendSearchURLsToRenderer(content::RenderProcessHost* rph) {
252 rph->Send(new ChromeViewMsg_SetSearchURLs( 244 rph->Send(new ChromeViewMsg_SetSearchURLs(
253 chrome::GetSearchURLs(profile_), chrome::GetNewTabPageURL(profile_))); 245 chrome::GetSearchURLs(profile_), chrome::GetNewTabPageURL(profile_)));
254 } 246 }
255 247
256 void InstantService::OnOmniboxStartMarginChanged(int start_margin) { 248 void InstantService::OnOmniboxStartMarginChanged(int start_margin) {
257 omnibox_start_margin_ = start_margin; 249 omnibox_start_margin_ = start_margin;
258 FOR_EACH_OBSERVER(InstantServiceObserver, observers_, 250 FOR_EACH_OBSERVER(InstantServiceObserver, observers_,
259 OmniboxStartMarginChanged(omnibox_start_margin_)); 251 OmniboxStartMarginChanged(omnibox_start_margin_));
260 } 252 }
261 253
262 void InstantService::OnRendererProcessTerminated(int process_id) { 254 void InstantService::OnRendererProcessTerminated(int process_id) {
263 process_ids_.erase(process_id); 255 process_ids_.erase(process_id);
264 256
265 if (instant_io_context_.get()) { 257 if (instant_io_context_.get()) {
266 BrowserThread::PostTask( 258 content::BrowserThread::PostTask(
267 BrowserThread::IO, 259 content::BrowserThread::IO, FROM_HERE,
268 FROM_HERE,
269 base::Bind(&InstantIOContext::RemoveInstantProcessOnIO, 260 base::Bind(&InstantIOContext::RemoveInstantProcessOnIO,
270 instant_io_context_, 261 instant_io_context_, process_id));
271 process_id));
272 } 262 }
273 } 263 }
274 264
275 void InstantService::OnMostVisitedItemsReceived( 265 void InstantService::OnMostVisitedItemsReceived(
276 const history::MostVisitedURLList& data) { 266 const history::MostVisitedURLList& data) {
277 history::MostVisitedURLList reordered_data(data); 267 history::MostVisitedURLList reordered_data(data);
278 history::MostVisitedTilesExperiment::MaybeShuffle(&reordered_data); 268 history::MostVisitedTilesExperiment::MaybeShuffle(&reordered_data);
279 269
280 std::vector<InstantMostVisitedItem> new_most_visited_items; 270 std::vector<InstantMostVisitedItem> new_most_visited_items;
281 for (size_t i = 0; i < reordered_data.size(); i++) { 271 for (size_t i = 0; i < reordered_data.size(); i++) {
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
396 theme_info_->image_height = image->height(); 386 theme_info_->image_height = image->height();
397 387
398 theme_info_->has_attribution = 388 theme_info_->has_attribution =
399 theme_service->HasCustomImage(IDR_THEME_NTP_ATTRIBUTION); 389 theme_service->HasCustomImage(IDR_THEME_NTP_ATTRIBUTION);
400 } 390 }
401 391
402 FOR_EACH_OBSERVER(InstantServiceObserver, observers_, 392 FOR_EACH_OBSERVER(InstantServiceObserver, observers_,
403 ThemeInfoChanged(*theme_info_)); 393 ThemeInfoChanged(*theme_info_));
404 } 394 }
405 395
406 void InstantService::OnGoogleURLUpdated( 396 void InstantService::OnTemplateURLServiceChanged() {
407 Profile* profile, 397 // Check whether the default search provider was changed.
408 GoogleURLTracker::UpdatedDetails* details) { 398 const TemplateURL* template_url =
409 GURL last_prompted_url( 399 template_url_service_->GetDefaultSearchProvider();
410 profile->GetPrefs()->GetString(prefs::kLastPromptedGoogleURL)); 400 bool default_search_provider_changed = !TemplateURL::MatchesData(
411 401 template_url, previous_default_search_provider_.get());
412 // See GoogleURLTracker::OnURLFetchComplete(). 402 if (default_search_provider_changed) {
413 // last_prompted_url.is_empty() indicates very first run of Chrome. So there 403 previous_default_search_provider_.reset(
414 // is no need to notify, as there won't be any old state. 404 template_url ? new TemplateURLData(template_url->data()) : NULL);
415 if (last_prompted_url.is_empty())
416 return;
417
418 ResetInstantSearchPrerenderer();
419
420 // Only the scheme changed. Ignore it since we do not prompt the user in this
421 // case.
422 if (net::StripWWWFromHost(details->first) ==
423 net::StripWWWFromHost(details->second))
424 return;
425
426 FOR_EACH_OBSERVER(InstantServiceObserver, observers_, GoogleURLUpdated());
427 }
428
429 void InstantService::OnDefaultSearchProviderChanged(
430 const std::string& pref_name) {
431 DCHECK_EQ(pref_name, std::string(prefs::kDefaultSearchProviderID));
432 const TemplateURL* template_url = TemplateURLServiceFactory::GetForProfile(
433 profile_)->GetDefaultSearchProvider();
434 if (!template_url) {
435 // A NULL |template_url| could mean either this notification is sent during
436 // the browser start up operation or the user now has no default search
437 // provider. There is no way for the user to reach this state using the
438 // Chrome settings. Only explicitly poking at the DB or bugs in the Sync
439 // could cause that, neither of which we support.
440 return;
441 } 405 }
442 406
443 ResetInstantSearchPrerenderer(); 407 // Note that, even if the TemplateURL for the Default Search Provider has not
408 // changed, the effective URLs might change if they reference the Google base
409 // URL. The TemplateURLService will notify us when the effective URL changes
410 // in this way but it's up to us to do the work to check both.
411 GURL google_base_url(UIThreadSearchTermsData(profile_).GoogleBaseURLValue());
412 if (google_base_url != previous_google_base_url_) {
413 previous_google_base_url_ = google_base_url;
414 if (template_url && template_url->HasGoogleBaseURLs())
415 default_search_provider_changed = true;
416 }
444 417
445 FOR_EACH_OBSERVER( 418 if (default_search_provider_changed) {
446 InstantServiceObserver, observers_, DefaultSearchProviderChanged()); 419 ResetInstantSearchPrerenderer();
420 FOR_EACH_OBSERVER(InstantServiceObserver, observers_,
421 DefaultSearchProviderChanged());
422 }
447 } 423 }
448 424
449 void InstantService::ResetInstantSearchPrerenderer() { 425 void InstantService::ResetInstantSearchPrerenderer() {
450 if (!chrome::ShouldPrefetchSearchResults()) 426 if (!chrome::ShouldPrefetchSearchResults())
451 return; 427 return;
452 428
453 GURL url(chrome::GetSearchResultPrefetchBaseURL(profile_)); 429 GURL url(chrome::GetSearchResultPrefetchBaseURL(profile_));
454 if (url.is_valid()) 430 instant_prerenderer_.reset(
455 instant_prerenderer_.reset(new InstantSearchPrerenderer(profile_, url)); 431 url.is_valid() ? new InstantSearchPrerenderer(profile_, url) : NULL);
456 else
457 instant_prerenderer_.reset();
458 } 432 }
OLDNEW
« no previous file with comments | « chrome/browser/search/instant_service.h ('k') | chrome/browser/search/instant_service_observer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698