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

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. 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_)),
Peter Kasting 2014/05/08 18:23:37 I purposefully didn't do this in order to decouple
erikwright (departed) 2014/05/08 18:26:00 No. InstantServiceFactory declares a dependency on
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_) {
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 }
92 instant_io_context_ = new InstantIOContext(); 93 instant_io_context_ = new InstantIOContext();
Peter Kasting 2014/05/08 18:23:37 If this line needs to be here rather than in the i
erikwright (departed) 2014/05/08 19:23:11 Done.
93 94
94 if (profile_ && profile_->GetResourceContext()) { 95 if (profile_ && profile_->GetResourceContext()) {
95 BrowserThread::PostTask( 96 content::BrowserThread::PostTask(
96 BrowserThread::IO, FROM_HERE, 97 content::BrowserThread::IO, FROM_HERE,
97 base::Bind(&InstantIOContext::SetUserDataOnIO, 98 base::Bind(&InstantIOContext::SetUserDataOnIO,
98 profile->GetResourceContext(), instant_io_context_)); 99 profile->GetResourceContext(), instant_io_context_));
99 } 100 }
100 101
101 // Set up the data sources that Instant uses on the NTP. 102 // Set up the data sources that Instant uses on the NTP.
102 #if defined(ENABLE_THEMES) 103 #if defined(ENABLE_THEMES)
103 // Listen for theme installation. 104 // Listen for theme installation.
104 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED, 105 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
105 content::Source<ThemeService>( 106 content::Source<ThemeService>(
106 ThemeServiceFactory::GetForProfile(profile_))); 107 ThemeServiceFactory::GetForProfile(profile_)));
107 108
108 content::URLDataSource::Add(profile_, new ThemeSource(profile_)); 109 content::URLDataSource::Add(profile_, new ThemeSource(profile_));
109 #endif // defined(ENABLE_THEMES) 110 #endif // defined(ENABLE_THEMES)
110 111
111 // TODO(aurimas) remove this #if once instant_service.cc is no longer compiled 112 // TODO(aurimas) remove this #if once instant_service.cc is no longer compiled
112 // on Android. 113 // on Android.
113 #if !defined(OS_ANDROID) 114 #if !defined(OS_ANDROID)
114 content::URLDataSource::Add(profile_, new ThumbnailSource(profile_, false)); 115 content::URLDataSource::Add(profile_, new ThumbnailSource(profile_, false));
115 content::URLDataSource::Add(profile_, new ThumbnailSource(profile_, true)); 116 content::URLDataSource::Add(profile_, new ThumbnailSource(profile_, true));
116 content::URLDataSource::Add(profile_, new ThumbnailListSource(profile_)); 117 content::URLDataSource::Add(profile_, new ThumbnailListSource(profile_));
117 #endif // !defined(OS_ANDROID) 118 #endif // !defined(OS_ANDROID)
118 119
119 content::URLDataSource::Add( 120 content::URLDataSource::Add(
120 profile_, new FaviconSource(profile_, FaviconSource::FAVICON)); 121 profile_, new FaviconSource(profile_, FaviconSource::FAVICON));
121 content::URLDataSource::Add(profile_, new LocalNtpSource(profile_)); 122 content::URLDataSource::Add(profile_, new LocalNtpSource(profile_));
122 content::URLDataSource::Add(profile_, new MostVisitedIframeSource()); 123 content::URLDataSource::Add(profile_, new MostVisitedIframeSource());
123 content::URLDataSource::Add( 124 content::URLDataSource::Add(
124 profile_, new suggestions::SuggestionsSource(profile_)); 125 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 } 126 }
135 127
136 InstantService::~InstantService() { 128 InstantService::~InstantService() {
129 if (template_url_service_)
130 template_url_service_->RemoveObserver(this);
137 } 131 }
138 132
139 void InstantService::AddInstantProcess(int process_id) { 133 void InstantService::AddInstantProcess(int process_id) {
140 process_ids_.insert(process_id); 134 process_ids_.insert(process_id);
141 135
142 if (instant_io_context_.get()) { 136 if (instant_io_context_.get()) {
143 BrowserThread::PostTask(BrowserThread::IO, 137 content::BrowserThread::PostTask(
144 FROM_HERE, 138 content::BrowserThread::IO, FROM_HERE,
145 base::Bind(&InstantIOContext::AddInstantProcessOnIO, 139 base::Bind(&InstantIOContext::AddInstantProcessOnIO,
146 instant_io_context_, 140 instant_io_context_, process_id));
147 process_id));
148 } 141 }
149 } 142 }
150 143
151 bool InstantService::IsInstantProcess(int process_id) const { 144 bool InstantService::IsInstantProcess(int process_id) const {
152 return process_ids_.find(process_id) != process_ids_.end(); 145 return process_ids_.find(process_id) != process_ids_.end();
153 } 146 }
154 147
155 void InstantService::AddObserver(InstantServiceObserver* observer) { 148 void InstantService::AddObserver(InstantServiceObserver* observer) {
156 observers_.AddObserver(observer); 149 observers_.AddObserver(observer);
157 } 150 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
194 } 187 }
195 188
196 void InstantService::UpdateMostVisitedItemsInfo() { 189 void InstantService::UpdateMostVisitedItemsInfo() {
197 NotifyAboutMostVisitedItems(); 190 NotifyAboutMostVisitedItems();
198 } 191 }
199 192
200 void InstantService::Shutdown() { 193 void InstantService::Shutdown() {
201 process_ids_.clear(); 194 process_ids_.clear();
202 195
203 if (instant_io_context_.get()) { 196 if (instant_io_context_.get()) {
204 BrowserThread::PostTask( 197 content::BrowserThread::PostTask(
205 BrowserThread::IO, 198 content::BrowserThread::IO, FROM_HERE,
206 FROM_HERE,
207 base::Bind(&InstantIOContext::ClearInstantProcessesOnIO, 199 base::Bind(&InstantIOContext::ClearInstantProcessesOnIO,
208 instant_io_context_)); 200 instant_io_context_));
209 } 201 }
210 instant_io_context_ = NULL; 202 instant_io_context_ = NULL;
211 } 203 }
212 204
213 void InstantService::Observe(int type, 205 void InstantService::Observe(int type,
214 const content::NotificationSource& source, 206 const content::NotificationSource& source,
215 const content::NotificationDetails& details) { 207 const content::NotificationDetails& details) {
216 switch (type) { 208 switch (type) {
(...skipping 13 matching lines...) Expand all
230 weak_ptr_factory_.GetWeakPtr()), false); 222 weak_ptr_factory_.GetWeakPtr()), false);
231 } 223 }
232 break; 224 break;
233 } 225 }
234 #if defined(ENABLE_THEMES) 226 #if defined(ENABLE_THEMES)
235 case chrome::NOTIFICATION_BROWSER_THEME_CHANGED: { 227 case chrome::NOTIFICATION_BROWSER_THEME_CHANGED: {
236 OnThemeChanged(content::Source<ThemeService>(source).ptr()); 228 OnThemeChanged(content::Source<ThemeService>(source).ptr());
237 break; 229 break;
238 } 230 }
239 #endif // defined(ENABLE_THEMES) 231 #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: 232 default:
247 NOTREACHED() << "Unexpected notification type in InstantService."; 233 NOTREACHED() << "Unexpected notification type in InstantService.";
248 } 234 }
249 } 235 }
250 236
251 void InstantService::SendSearchURLsToRenderer(content::RenderProcessHost* rph) { 237 void InstantService::SendSearchURLsToRenderer(content::RenderProcessHost* rph) {
252 rph->Send(new ChromeViewMsg_SetSearchURLs( 238 rph->Send(new ChromeViewMsg_SetSearchURLs(
253 chrome::GetSearchURLs(profile_), chrome::GetNewTabPageURL(profile_))); 239 chrome::GetSearchURLs(profile_), chrome::GetNewTabPageURL(profile_)));
254 } 240 }
255 241
256 void InstantService::OnOmniboxStartMarginChanged(int start_margin) { 242 void InstantService::OnOmniboxStartMarginChanged(int start_margin) {
257 omnibox_start_margin_ = start_margin; 243 omnibox_start_margin_ = start_margin;
258 FOR_EACH_OBSERVER(InstantServiceObserver, observers_, 244 FOR_EACH_OBSERVER(InstantServiceObserver, observers_,
259 OmniboxStartMarginChanged(omnibox_start_margin_)); 245 OmniboxStartMarginChanged(omnibox_start_margin_));
260 } 246 }
261 247
262 void InstantService::OnRendererProcessTerminated(int process_id) { 248 void InstantService::OnRendererProcessTerminated(int process_id) {
263 process_ids_.erase(process_id); 249 process_ids_.erase(process_id);
264 250
265 if (instant_io_context_.get()) { 251 if (instant_io_context_.get()) {
266 BrowserThread::PostTask( 252 content::BrowserThread::PostTask(
267 BrowserThread::IO, 253 content::BrowserThread::IO, FROM_HERE,
268 FROM_HERE,
269 base::Bind(&InstantIOContext::RemoveInstantProcessOnIO, 254 base::Bind(&InstantIOContext::RemoveInstantProcessOnIO,
270 instant_io_context_, 255 instant_io_context_, process_id));
271 process_id));
272 } 256 }
273 } 257 }
274 258
275 void InstantService::OnMostVisitedItemsReceived( 259 void InstantService::OnMostVisitedItemsReceived(
276 const history::MostVisitedURLList& data) { 260 const history::MostVisitedURLList& data) {
277 history::MostVisitedURLList reordered_data(data); 261 history::MostVisitedURLList reordered_data(data);
278 history::MostVisitedTilesExperiment::MaybeShuffle(&reordered_data); 262 history::MostVisitedTilesExperiment::MaybeShuffle(&reordered_data);
279 263
280 std::vector<InstantMostVisitedItem> new_most_visited_items; 264 std::vector<InstantMostVisitedItem> new_most_visited_items;
281 for (size_t i = 0; i < reordered_data.size(); i++) { 265 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(); 380 theme_info_->image_height = image->height();
397 381
398 theme_info_->has_attribution = 382 theme_info_->has_attribution =
399 theme_service->HasCustomImage(IDR_THEME_NTP_ATTRIBUTION); 383 theme_service->HasCustomImage(IDR_THEME_NTP_ATTRIBUTION);
400 } 384 }
401 385
402 FOR_EACH_OBSERVER(InstantServiceObserver, observers_, 386 FOR_EACH_OBSERVER(InstantServiceObserver, observers_,
403 ThemeInfoChanged(*theme_info_)); 387 ThemeInfoChanged(*theme_info_));
404 } 388 }
405 389
406 void InstantService::OnGoogleURLUpdated( 390 void InstantService::OnTemplateURLServiceChanged() {
407 Profile* profile, 391 // Check whether the default search provider was changed.
408 GoogleURLTracker::UpdatedDetails* details) { 392 const TemplateURL* template_url =
409 GURL last_prompted_url( 393 template_url_service_->GetDefaultSearchProvider();
410 profile->GetPrefs()->GetString(prefs::kLastPromptedGoogleURL)); 394 bool default_search_provider_changed = !TemplateURL::MatchesData(
411 395 template_url, previous_default_search_provider_.get());
412 // See GoogleURLTracker::OnURLFetchComplete(). 396 if (default_search_provider_changed) {
413 // last_prompted_url.is_empty() indicates very first run of Chrome. So there 397 previous_default_search_provider_.reset(
414 // is no need to notify, as there won't be any old state. 398 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 } 399 }
442 400
443 ResetInstantSearchPrerenderer(); 401 // If the default search provider uses Google base URLs, we also care whether
402 // the Google base URL changed.
403 GURL google_base_url(UIThreadSearchTermsData(profile_).GoogleBaseURLValue());
404 if (google_base_url != previous_google_base_url_) {
405 previous_google_base_url_ = google_base_url;
406 if (template_url && template_url->HasGoogleBaseURLs())
407 default_search_provider_changed = true;
408 }
444 409
445 FOR_EACH_OBSERVER( 410 if (default_search_provider_changed) {
446 InstantServiceObserver, observers_, DefaultSearchProviderChanged()); 411 ResetInstantSearchPrerenderer();
412 if (!chrome::ShouldPrefetchSearchResults())
Peter Kasting 2014/05/08 18:23:37 This check wasn't in the old code, and it's not cl
erikwright (departed) 2014/05/08 19:23:11 Someone who contributed to this CL (there have bee
Peter Kasting 2014/05/08 20:17:41 I made that change, and this code should work with
413 return;
Peter Kasting 2014/05/08 18:23:37 In this case, I'd prefer to either reverse the con
erikwright (departed) 2014/05/08 19:23:11 N/A.
414
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
« 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