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

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: Review feedback. 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 // Stub for unit tests.
74 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) 63 if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI))
75 return; 64 return;
65 previous_google_base_url_ =
66 GURL(UIThreadSearchTermsData(profile).GoogleBaseURLValue());
67
68 if (template_url_service_) {
Jered 2014/05/08 20:20:05 When would this be null? Should this crash, instea
Peter Kasting 2014/05/08 20:40:04 Yeah, it sounds like this can be NULL in tests, an
erikwright (departed) 2014/05/08 20:52:59 Done.
69 template_url_service_->AddObserver(this);
70 const TemplateURL* default_search_provider =
71 template_url_service_->GetDefaultSearchProvider();
72 if (default_search_provider) {
73 previous_default_search_provider_.reset(
74 new TemplateURLData(default_search_provider->data()));
75 }
76 }
76 77
77 ResetInstantSearchPrerenderer(); 78 ResetInstantSearchPrerenderer();
78 79
79 registrar_.Add(this, 80 registrar_.Add(this,
80 content::NOTIFICATION_RENDERER_PROCESS_CREATED, 81 content::NOTIFICATION_RENDERER_PROCESS_CREATED,
81 content::NotificationService::AllSources()); 82 content::NotificationService::AllSources());
82 registrar_.Add(this, 83 registrar_.Add(this,
83 content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, 84 content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
84 content::NotificationService::AllSources()); 85 content::NotificationService::AllSources());
85 86
86 history::TopSites* top_sites = profile_->GetTopSites(); 87 history::TopSites* top_sites = profile_->GetTopSites();
87 if (top_sites) { 88 if (top_sites) {
88 registrar_.Add(this, 89 registrar_.Add(this,
89 chrome::NOTIFICATION_TOP_SITES_CHANGED, 90 chrome::NOTIFICATION_TOP_SITES_CHANGED,
90 content::Source<history::TopSites>(top_sites)); 91 content::Source<history::TopSites>(top_sites));
91 } 92 }
93
94 // This depends on the existence of the typical browser threads. Therefore it
95 // is only instantiated here (after the check for a UI thread above).
92 instant_io_context_ = new InstantIOContext(); 96 instant_io_context_ = new InstantIOContext();
93 97
94 if (profile_ && profile_->GetResourceContext()) { 98 if (profile_ && profile_->GetResourceContext()) {
95 BrowserThread::PostTask( 99 content::BrowserThread::PostTask(
96 BrowserThread::IO, FROM_HERE, 100 content::BrowserThread::IO, FROM_HERE,
97 base::Bind(&InstantIOContext::SetUserDataOnIO, 101 base::Bind(&InstantIOContext::SetUserDataOnIO,
98 profile->GetResourceContext(), instant_io_context_)); 102 profile->GetResourceContext(), instant_io_context_));
99 } 103 }
100 104
101 // Set up the data sources that Instant uses on the NTP. 105 // Set up the data sources that Instant uses on the NTP.
102 #if defined(ENABLE_THEMES) 106 #if defined(ENABLE_THEMES)
103 // Listen for theme installation. 107 // Listen for theme installation.
104 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED, 108 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
105 content::Source<ThemeService>( 109 content::Source<ThemeService>(
106 ThemeServiceFactory::GetForProfile(profile_))); 110 ThemeServiceFactory::GetForProfile(profile_)));
107 111
108 content::URLDataSource::Add(profile_, new ThemeSource(profile_)); 112 content::URLDataSource::Add(profile_, new ThemeSource(profile_));
109 #endif // defined(ENABLE_THEMES) 113 #endif // defined(ENABLE_THEMES)
110 114
111 // TODO(aurimas) remove this #if once instant_service.cc is no longer compiled 115 // TODO(aurimas) remove this #if once instant_service.cc is no longer compiled
112 // on Android. 116 // on Android.
113 #if !defined(OS_ANDROID) 117 #if !defined(OS_ANDROID)
114 content::URLDataSource::Add(profile_, new ThumbnailSource(profile_, false)); 118 content::URLDataSource::Add(profile_, new ThumbnailSource(profile_, false));
115 content::URLDataSource::Add(profile_, new ThumbnailSource(profile_, true)); 119 content::URLDataSource::Add(profile_, new ThumbnailSource(profile_, true));
116 content::URLDataSource::Add(profile_, new ThumbnailListSource(profile_)); 120 content::URLDataSource::Add(profile_, new ThumbnailListSource(profile_));
117 #endif // !defined(OS_ANDROID) 121 #endif // !defined(OS_ANDROID)
118 122
119 content::URLDataSource::Add( 123 content::URLDataSource::Add(
120 profile_, new FaviconSource(profile_, FaviconSource::FAVICON)); 124 profile_, new FaviconSource(profile_, FaviconSource::FAVICON));
121 content::URLDataSource::Add(profile_, new LocalNtpSource(profile_)); 125 content::URLDataSource::Add(profile_, new LocalNtpSource(profile_));
122 content::URLDataSource::Add(profile_, new MostVisitedIframeSource()); 126 content::URLDataSource::Add(profile_, new MostVisitedIframeSource());
123 content::URLDataSource::Add( 127 content::URLDataSource::Add(
124 profile_, new suggestions::SuggestionsSource(profile_)); 128 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 } 129 }
135 130
136 InstantService::~InstantService() { 131 InstantService::~InstantService() {
132 if (template_url_service_)
133 template_url_service_->RemoveObserver(this);
137 } 134 }
138 135
139 void InstantService::AddInstantProcess(int process_id) { 136 void InstantService::AddInstantProcess(int process_id) {
140 process_ids_.insert(process_id); 137 process_ids_.insert(process_id);
141 138
142 if (instant_io_context_.get()) { 139 if (instant_io_context_.get()) {
143 BrowserThread::PostTask(BrowserThread::IO, 140 content::BrowserThread::PostTask(
144 FROM_HERE, 141 content::BrowserThread::IO, FROM_HERE,
145 base::Bind(&InstantIOContext::AddInstantProcessOnIO, 142 base::Bind(&InstantIOContext::AddInstantProcessOnIO,
146 instant_io_context_, 143 instant_io_context_, process_id));
147 process_id));
148 } 144 }
149 } 145 }
150 146
151 bool InstantService::IsInstantProcess(int process_id) const { 147 bool InstantService::IsInstantProcess(int process_id) const {
152 return process_ids_.find(process_id) != process_ids_.end(); 148 return process_ids_.find(process_id) != process_ids_.end();
153 } 149 }
154 150
155 void InstantService::AddObserver(InstantServiceObserver* observer) { 151 void InstantService::AddObserver(InstantServiceObserver* observer) {
156 observers_.AddObserver(observer); 152 observers_.AddObserver(observer);
157 } 153 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
194 } 190 }
195 191
196 void InstantService::UpdateMostVisitedItemsInfo() { 192 void InstantService::UpdateMostVisitedItemsInfo() {
197 NotifyAboutMostVisitedItems(); 193 NotifyAboutMostVisitedItems();
198 } 194 }
199 195
200 void InstantService::Shutdown() { 196 void InstantService::Shutdown() {
201 process_ids_.clear(); 197 process_ids_.clear();
202 198
203 if (instant_io_context_.get()) { 199 if (instant_io_context_.get()) {
204 BrowserThread::PostTask( 200 content::BrowserThread::PostTask(
205 BrowserThread::IO, 201 content::BrowserThread::IO, FROM_HERE,
206 FROM_HERE,
207 base::Bind(&InstantIOContext::ClearInstantProcessesOnIO, 202 base::Bind(&InstantIOContext::ClearInstantProcessesOnIO,
208 instant_io_context_)); 203 instant_io_context_));
209 } 204 }
210 instant_io_context_ = NULL; 205 instant_io_context_ = NULL;
211 } 206 }
212 207
213 void InstantService::Observe(int type, 208 void InstantService::Observe(int type,
214 const content::NotificationSource& source, 209 const content::NotificationSource& source,
215 const content::NotificationDetails& details) { 210 const content::NotificationDetails& details) {
216 switch (type) { 211 switch (type) {
(...skipping 13 matching lines...) Expand all
230 weak_ptr_factory_.GetWeakPtr()), false); 225 weak_ptr_factory_.GetWeakPtr()), false);
231 } 226 }
232 break; 227 break;
233 } 228 }
234 #if defined(ENABLE_THEMES) 229 #if defined(ENABLE_THEMES)
235 case chrome::NOTIFICATION_BROWSER_THEME_CHANGED: { 230 case chrome::NOTIFICATION_BROWSER_THEME_CHANGED: {
236 OnThemeChanged(content::Source<ThemeService>(source).ptr()); 231 OnThemeChanged(content::Source<ThemeService>(source).ptr());
237 break; 232 break;
238 } 233 }
239 #endif // defined(ENABLE_THEMES) 234 #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: 235 default:
247 NOTREACHED() << "Unexpected notification type in InstantService."; 236 NOTREACHED() << "Unexpected notification type in InstantService.";
248 } 237 }
249 } 238 }
250 239
251 void InstantService::SendSearchURLsToRenderer(content::RenderProcessHost* rph) { 240 void InstantService::SendSearchURLsToRenderer(content::RenderProcessHost* rph) {
252 rph->Send(new ChromeViewMsg_SetSearchURLs( 241 rph->Send(new ChromeViewMsg_SetSearchURLs(
253 chrome::GetSearchURLs(profile_), chrome::GetNewTabPageURL(profile_))); 242 chrome::GetSearchURLs(profile_), chrome::GetNewTabPageURL(profile_)));
254 } 243 }
255 244
256 void InstantService::OnOmniboxStartMarginChanged(int start_margin) { 245 void InstantService::OnOmniboxStartMarginChanged(int start_margin) {
257 omnibox_start_margin_ = start_margin; 246 omnibox_start_margin_ = start_margin;
258 FOR_EACH_OBSERVER(InstantServiceObserver, observers_, 247 FOR_EACH_OBSERVER(InstantServiceObserver, observers_,
259 OmniboxStartMarginChanged(omnibox_start_margin_)); 248 OmniboxStartMarginChanged(omnibox_start_margin_));
260 } 249 }
261 250
262 void InstantService::OnRendererProcessTerminated(int process_id) { 251 void InstantService::OnRendererProcessTerminated(int process_id) {
263 process_ids_.erase(process_id); 252 process_ids_.erase(process_id);
264 253
265 if (instant_io_context_.get()) { 254 if (instant_io_context_.get()) {
266 BrowserThread::PostTask( 255 content::BrowserThread::PostTask(
267 BrowserThread::IO, 256 content::BrowserThread::IO, FROM_HERE,
268 FROM_HERE,
269 base::Bind(&InstantIOContext::RemoveInstantProcessOnIO, 257 base::Bind(&InstantIOContext::RemoveInstantProcessOnIO,
270 instant_io_context_, 258 instant_io_context_, process_id));
271 process_id));
272 } 259 }
273 } 260 }
274 261
275 void InstantService::OnMostVisitedItemsReceived( 262 void InstantService::OnMostVisitedItemsReceived(
276 const history::MostVisitedURLList& data) { 263 const history::MostVisitedURLList& data) {
277 history::MostVisitedURLList reordered_data(data); 264 history::MostVisitedURLList reordered_data(data);
278 history::MostVisitedTilesExperiment::MaybeShuffle(&reordered_data); 265 history::MostVisitedTilesExperiment::MaybeShuffle(&reordered_data);
279 266
280 std::vector<InstantMostVisitedItem> new_most_visited_items; 267 std::vector<InstantMostVisitedItem> new_most_visited_items;
281 for (size_t i = 0; i < reordered_data.size(); i++) { 268 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(); 383 theme_info_->image_height = image->height();
397 384
398 theme_info_->has_attribution = 385 theme_info_->has_attribution =
399 theme_service->HasCustomImage(IDR_THEME_NTP_ATTRIBUTION); 386 theme_service->HasCustomImage(IDR_THEME_NTP_ATTRIBUTION);
400 } 387 }
401 388
402 FOR_EACH_OBSERVER(InstantServiceObserver, observers_, 389 FOR_EACH_OBSERVER(InstantServiceObserver, observers_,
403 ThemeInfoChanged(*theme_info_)); 390 ThemeInfoChanged(*theme_info_));
404 } 391 }
405 392
406 void InstantService::OnGoogleURLUpdated( 393 void InstantService::OnTemplateURLServiceChanged() {
407 Profile* profile, 394 // Check whether the default search provider was changed.
408 GoogleURLTracker::UpdatedDetails* details) { 395 const TemplateURL* template_url =
409 GURL last_prompted_url( 396 template_url_service_->GetDefaultSearchProvider();
410 profile->GetPrefs()->GetString(prefs::kLastPromptedGoogleURL)); 397 bool default_search_provider_changed = !TemplateURL::MatchesData(
411 398 template_url, previous_default_search_provider_.get());
412 // See GoogleURLTracker::OnURLFetchComplete(). 399 if (default_search_provider_changed) {
413 // last_prompted_url.is_empty() indicates very first run of Chrome. So there 400 previous_default_search_provider_.reset(
414 // is no need to notify, as there won't be any old state. 401 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 } 402 }
442 403
443 ResetInstantSearchPrerenderer(); 404 // If the default search provider uses Google base URLs, we also care whether
405 // the Google base URL changed.
406 GURL google_base_url(UIThreadSearchTermsData(profile_).GoogleBaseURLValue());
407 if (google_base_url != previous_google_base_url_) {
408 previous_google_base_url_ = google_base_url;
409 if (template_url && template_url->HasGoogleBaseURLs())
Jered 2014/05/08 20:20:05 Why is a change not a change when !HasGoogleBaseUR
Peter Kasting 2014/05/08 20:40:04 We already checked above that nothing about the de
erikwright (departed) 2014/05/08 20:52:59 There were two comments already in the method, but
Jered 2014/05/08 21:02:25 Gotcha. So MatchesData() implies that old_template
410 default_search_provider_changed = true;
411 }
444 412
445 FOR_EACH_OBSERVER( 413 if (default_search_provider_changed) {
446 InstantServiceObserver, observers_, DefaultSearchProviderChanged()); 414 ResetInstantSearchPrerenderer();
415 FOR_EACH_OBSERVER(InstantServiceObserver, observers_,
416 DefaultSearchProviderChanged());
417 }
447 } 418 }
448 419
449 void InstantService::ResetInstantSearchPrerenderer() { 420 void InstantService::ResetInstantSearchPrerenderer() {
450 if (!chrome::ShouldPrefetchSearchResults()) 421 if (!chrome::ShouldPrefetchSearchResults())
451 return; 422 return;
452 423
453 GURL url(chrome::GetSearchResultPrefetchBaseURL(profile_)); 424 GURL url(chrome::GetSearchResultPrefetchBaseURL(profile_));
454 if (url.is_valid()) 425 instant_prerenderer_.reset(
455 instant_prerenderer_.reset(new InstantSearchPrerenderer(profile_, url)); 426 url.is_valid() ? new InstantSearchPrerenderer(profile_, url) : NULL);
456 else
457 instant_prerenderer_.reset();
458 } 427 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698