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

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

Powered by Google App Engine
This is Rietveld 408576698