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

Side by Side Diff: chrome/browser/autocomplete/base_search_provider.cc

Issue 500023002: Introduce AutocompleteProviderDelegate (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address comments Created 6 years, 4 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
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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/autocomplete/base_search_provider.h" 5 #include "chrome/browser/autocomplete/base_search_provider.h"
6 6
7 #include "base/i18n/case_conversion.h" 7 #include "base/i18n/case_conversion.h"
8 #include "base/prefs/pref_registry_simple.h"
9 #include "base/prefs/pref_service.h"
10 #include "base/strings/string_util.h" 8 #include "base/strings/string_util.h"
11 #include "base/strings/utf_string_conversions.h" 9 #include "base/strings/utf_string_conversions.h"
12 #include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h"
13 #include "chrome/browser/bitmap_fetcher/bitmap_fetcher_service.h"
14 #include "chrome/browser/bitmap_fetcher/bitmap_fetcher_service_factory.h"
15 #include "chrome/browser/history/history_service.h"
16 #include "chrome/browser/history/history_service_factory.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/sync/profile_sync_service.h"
19 #include "chrome/browser/sync/profile_sync_service_factory.h"
20 #include "chrome/common/pref_names.h"
21 #include "components/metrics/proto/omnibox_event.pb.h" 10 #include "components/metrics/proto/omnibox_event.pb.h"
22 #include "components/metrics/proto/omnibox_input_type.pb.h" 11 #include "components/metrics/proto/omnibox_input_type.pb.h"
12 #include "components/omnibox/autocomplete_provider_delegate.h"
23 #include "components/omnibox/autocomplete_provider_listener.h" 13 #include "components/omnibox/autocomplete_provider_listener.h"
24 #include "components/omnibox/omnibox_field_trial.h" 14 #include "components/omnibox/omnibox_field_trial.h"
25 #include "components/search_engines/template_url.h" 15 #include "components/search_engines/template_url.h"
26 #include "components/search_engines/template_url_prepopulate_data.h" 16 #include "components/search_engines/template_url_prepopulate_data.h"
27 #include "components/search_engines/template_url_service.h" 17 #include "components/search_engines/template_url_service.h"
28 #include "components/sync_driver/sync_prefs.h"
29 #include "net/base/escape.h"
30 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" 18 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
31 #include "net/url_request/url_fetcher.h" 19 #include "net/url_request/url_fetcher.h"
32 #include "net/url_request/url_fetcher_delegate.h" 20 #include "net/url_request/url_fetcher_delegate.h"
33 #include "url/gurl.h" 21 #include "url/gurl.h"
34 22
35 using metrics::OmniboxEventProto; 23 using metrics::OmniboxEventProto;
36 24
37 // SuggestionDeletionHandler ------------------------------------------------- 25 // SuggestionDeletionHandler -------------------------------------------------
38 26
39 // This class handles making requests to the server in order to delete 27 // This class handles making requests to the server in order to delete
40 // personalized suggestions. 28 // personalized suggestions.
41 class SuggestionDeletionHandler : public net::URLFetcherDelegate { 29 class SuggestionDeletionHandler : public net::URLFetcherDelegate {
42 public: 30 public:
43 typedef base::Callback<void(bool, SuggestionDeletionHandler*)> 31 typedef base::Callback<void(bool, SuggestionDeletionHandler*)>
44 DeletionCompletedCallback; 32 DeletionCompletedCallback;
45 33
46 SuggestionDeletionHandler( 34 SuggestionDeletionHandler(
47 const std::string& deletion_url, 35 const std::string& deletion_url,
48 Profile* profile, 36 net::URLRequestContextGetter* request_context,
49 const DeletionCompletedCallback& callback); 37 const DeletionCompletedCallback& callback);
50 38
51 virtual ~SuggestionDeletionHandler(); 39 virtual ~SuggestionDeletionHandler();
52 40
53 private: 41 private:
54 // net::URLFetcherDelegate: 42 // net::URLFetcherDelegate:
55 virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE; 43 virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
56 44
57 scoped_ptr<net::URLFetcher> deletion_fetcher_; 45 scoped_ptr<net::URLFetcher> deletion_fetcher_;
58 DeletionCompletedCallback callback_; 46 DeletionCompletedCallback callback_;
59 47
60 DISALLOW_COPY_AND_ASSIGN(SuggestionDeletionHandler); 48 DISALLOW_COPY_AND_ASSIGN(SuggestionDeletionHandler);
61 }; 49 };
62 50
63 SuggestionDeletionHandler::SuggestionDeletionHandler( 51 SuggestionDeletionHandler::SuggestionDeletionHandler(
64 const std::string& deletion_url, 52 const std::string& deletion_url,
65 Profile* profile, 53 net::URLRequestContextGetter* request_context,
66 const DeletionCompletedCallback& callback) : callback_(callback) { 54 const DeletionCompletedCallback& callback) : callback_(callback) {
67 GURL url(deletion_url); 55 GURL url(deletion_url);
68 DCHECK(url.is_valid()); 56 DCHECK(url.is_valid());
69 57
70 deletion_fetcher_.reset(net::URLFetcher::Create( 58 deletion_fetcher_.reset(net::URLFetcher::Create(
71 BaseSearchProvider::kDeletionURLFetcherID, 59 BaseSearchProvider::kDeletionURLFetcherID,
72 url, 60 url,
73 net::URLFetcher::GET, 61 net::URLFetcher::GET,
74 this)); 62 this));
75 deletion_fetcher_->SetRequestContext(profile->GetRequestContext()); 63 deletion_fetcher_->SetRequestContext(request_context);
76 deletion_fetcher_->Start(); 64 deletion_fetcher_->Start();
77 } 65 }
78 66
79 SuggestionDeletionHandler::~SuggestionDeletionHandler() { 67 SuggestionDeletionHandler::~SuggestionDeletionHandler() {
80 } 68 }
81 69
82 void SuggestionDeletionHandler::OnURLFetchComplete( 70 void SuggestionDeletionHandler::OnURLFetchComplete(
83 const net::URLFetcher* source) { 71 const net::URLFetcher* source) {
84 DCHECK(source == deletion_fetcher_.get()); 72 DCHECK(source == deletion_fetcher_.get());
85 callback_.Run( 73 callback_.Run(
86 source->GetStatus().is_success() && (source->GetResponseCode() == 200), 74 source->GetStatus().is_success() && (source->GetResponseCode() == 200),
87 this); 75 this);
88 } 76 }
89 77
90 // BaseSearchProvider --------------------------------------------------------- 78 // BaseSearchProvider ---------------------------------------------------------
91 79
92 // static 80 // static
93 const int BaseSearchProvider::kDefaultProviderURLFetcherID = 1; 81 const int BaseSearchProvider::kDefaultProviderURLFetcherID = 1;
94 const int BaseSearchProvider::kKeywordProviderURLFetcherID = 2; 82 const int BaseSearchProvider::kKeywordProviderURLFetcherID = 2;
95 const int BaseSearchProvider::kDeletionURLFetcherID = 3; 83 const int BaseSearchProvider::kDeletionURLFetcherID = 3;
96 84
97 BaseSearchProvider::BaseSearchProvider(TemplateURLService* template_url_service, 85 BaseSearchProvider::BaseSearchProvider(
98 Profile* profile, 86 TemplateURLService* template_url_service,
99 AutocompleteProvider::Type type) 87 scoped_ptr<AutocompleteProviderDelegate> delegate,
88 AutocompleteProvider::Type type)
100 : AutocompleteProvider(type), 89 : AutocompleteProvider(type),
101 template_url_service_(template_url_service), 90 template_url_service_(template_url_service),
102 profile_(profile), 91 delegate_(delegate.Pass()),
103 field_trial_triggered_(false), 92 field_trial_triggered_(false),
104 field_trial_triggered_in_session_(false) { 93 field_trial_triggered_in_session_(false) {
105 } 94 }
106 95
107 // static 96 // static
108 bool BaseSearchProvider::ShouldPrefetch(const AutocompleteMatch& match) { 97 bool BaseSearchProvider::ShouldPrefetch(const AutocompleteMatch& match) {
109 return match.GetAdditionalInfo(kShouldPrefetchKey) == kTrue; 98 return match.GetAdditionalInfo(kShouldPrefetchKey) == kTrue;
110 } 99 }
111 100
112 // static 101 // static
(...skipping 12 matching lines...) Expand all
125 base::string16(), base::string16(), std::string(), std::string(), 114 base::string16(), base::string16(), std::string(), std::string(),
126 from_keyword_provider, 0, false, false, base::string16()), 115 from_keyword_provider, 0, false, false, base::string16()),
127 template_url, search_terms_data, 0, false); 116 template_url, search_terms_data, 0, false);
128 } 117 }
129 118
130 void BaseSearchProvider::DeleteMatch(const AutocompleteMatch& match) { 119 void BaseSearchProvider::DeleteMatch(const AutocompleteMatch& match) {
131 DCHECK(match.deletable); 120 DCHECK(match.deletable);
132 if (!match.GetAdditionalInfo(BaseSearchProvider::kDeletionUrlKey).empty()) { 121 if (!match.GetAdditionalInfo(BaseSearchProvider::kDeletionUrlKey).empty()) {
133 deletion_handlers_.push_back(new SuggestionDeletionHandler( 122 deletion_handlers_.push_back(new SuggestionDeletionHandler(
134 match.GetAdditionalInfo(BaseSearchProvider::kDeletionUrlKey), 123 match.GetAdditionalInfo(BaseSearchProvider::kDeletionUrlKey),
135 profile_, 124 delegate_->RequestContext(),
136 base::Bind(&BaseSearchProvider::OnDeletionComplete, 125 base::Bind(&BaseSearchProvider::OnDeletionComplete,
137 base::Unretained(this)))); 126 base::Unretained(this))));
138 } 127 }
139 128
140 HistoryService* const history_service =
141 HistoryServiceFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS);
142 TemplateURL* template_url = 129 TemplateURL* template_url =
143 match.GetTemplateURL(template_url_service_, false); 130 match.GetTemplateURL(template_url_service_, false);
144 // This may be NULL if the template corresponding to the keyword has been 131 // This may be NULL if the template corresponding to the keyword has been
145 // deleted or there is no keyword set. 132 // deleted or there is no keyword set.
146 if (template_url != NULL) { 133 if (template_url != NULL) {
147 history_service->DeleteMatchingURLsForKeyword(template_url->id(), 134 delegate_->DeleteMatchingURLsForKeywordFromHistory(template_url->id(),
148 match.contents); 135 match.contents);
149 } 136 }
150 137
151 // Immediately update the list of matches to show the match was deleted, 138 // Immediately update the list of matches to show the match was deleted,
152 // regardless of whether the server request actually succeeds. 139 // regardless of whether the server request actually succeeds.
153 DeleteMatchFromMatches(match); 140 DeleteMatchFromMatches(match);
154 } 141 }
155 142
156 void BaseSearchProvider::AddProviderInfo(ProvidersInfo* provider_info) const { 143 void BaseSearchProvider::AddProviderInfo(ProvidersInfo* provider_info) const {
157 provider_info->push_back(metrics::OmniboxEventProto_ProviderInfo()); 144 provider_info->push_back(metrics::OmniboxEventProto_ProviderInfo());
158 metrics::OmniboxEventProto_ProviderInfo& new_entry = provider_info->back(); 145 metrics::OmniboxEventProto_ProviderInfo& new_entry = provider_info->back();
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
279 266
280 return match; 267 return match;
281 } 268 }
282 269
283 // static 270 // static
284 bool BaseSearchProvider::ZeroSuggestEnabled( 271 bool BaseSearchProvider::ZeroSuggestEnabled(
285 const GURL& suggest_url, 272 const GURL& suggest_url,
286 const TemplateURL* template_url, 273 const TemplateURL* template_url,
287 OmniboxEventProto::PageClassification page_classification, 274 OmniboxEventProto::PageClassification page_classification,
288 const SearchTermsData& search_terms_data, 275 const SearchTermsData& search_terms_data,
289 Profile* profile) { 276 AutocompleteProviderDelegate* delegate) {
290 if (!OmniboxFieldTrial::InZeroSuggestFieldTrial()) 277 if (!OmniboxFieldTrial::InZeroSuggestFieldTrial())
291 return false; 278 return false;
292 279
293 // Make sure we are sending the suggest request through HTTPS to prevent 280 // Make sure we are sending the suggest request through HTTPS to prevent
294 // exposing the current page URL or personalized results without encryption. 281 // exposing the current page URL or personalized results without encryption.
295 if (!suggest_url.SchemeIs(url::kHttpsScheme)) 282 if (!suggest_url.SchemeIs(url::kHttpsScheme))
296 return false; 283 return false;
297 284
298 // Don't show zero suggest on the NTP. 285 // Don't show zero suggest on the NTP.
299 // TODO(hfung): Experiment with showing MostVisited zero suggest on NTP 286 // TODO(hfung): Experiment with showing MostVisited zero suggest on NTP
300 // under the conditions described in crbug.com/305366. 287 // under the conditions described in crbug.com/305366.
301 if ((page_classification == 288 if ((page_classification ==
302 OmniboxEventProto::INSTANT_NTP_WITH_FAKEBOX_AS_STARTING_FOCUS) || 289 OmniboxEventProto::INSTANT_NTP_WITH_FAKEBOX_AS_STARTING_FOCUS) ||
303 (page_classification == 290 (page_classification ==
304 OmniboxEventProto::INSTANT_NTP_WITH_OMNIBOX_AS_STARTING_FOCUS)) 291 OmniboxEventProto::INSTANT_NTP_WITH_OMNIBOX_AS_STARTING_FOCUS))
305 return false; 292 return false;
306 293
307 // Don't run if there's no profile or in incognito mode. 294 // Don't run if in incognito mode.
308 if (profile == NULL || profile->IsOffTheRecord()) 295 if (delegate->IsOffTheRecord())
309 return false; 296 return false;
310 297
311 // Don't run if we can't get preferences or search suggest is not enabled. 298 // Don't run if we can't get preferences or search suggest is not enabled.
312 PrefService* prefs = profile->GetPrefs(); 299 if (!delegate->SearchSuggestEnabled())
313 if (!prefs->GetBoolean(prefs::kSearchSuggestEnabled))
314 return false; 300 return false;
315 301
316 // Only make the request if we know that the provider supports zero suggest 302 // Only make the request if we know that the provider supports zero suggest
317 // (currently only the prepopulated Google provider). 303 // (currently only the prepopulated Google provider).
318 if (template_url == NULL || 304 if (template_url == NULL ||
319 !template_url->SupportsReplacement(search_terms_data) || 305 !template_url->SupportsReplacement(search_terms_data) ||
320 TemplateURLPrepopulateData::GetEngineType( 306 TemplateURLPrepopulateData::GetEngineType(
321 *template_url, search_terms_data) != SEARCH_ENGINE_GOOGLE) 307 *template_url, search_terms_data) != SEARCH_ENGINE_GOOGLE)
322 return false; 308 return false;
323 309
324 return true; 310 return true;
325 } 311 }
326 312
327 // static 313 // static
328 bool BaseSearchProvider::CanSendURL( 314 bool BaseSearchProvider::CanSendURL(
329 const GURL& current_page_url, 315 const GURL& current_page_url,
330 const GURL& suggest_url, 316 const GURL& suggest_url,
331 const TemplateURL* template_url, 317 const TemplateURL* template_url,
332 OmniboxEventProto::PageClassification page_classification, 318 OmniboxEventProto::PageClassification page_classification,
333 const SearchTermsData& search_terms_data, 319 const SearchTermsData& search_terms_data,
334 Profile* profile) { 320 AutocompleteProviderDelegate* delegate) {
335 if (!ZeroSuggestEnabled(suggest_url, template_url, page_classification, 321 if (!ZeroSuggestEnabled(suggest_url, template_url, page_classification,
336 search_terms_data, profile)) 322 search_terms_data, delegate))
337 return false; 323 return false;
338 324
339 if (!current_page_url.is_valid()) 325 if (!current_page_url.is_valid())
340 return false; 326 return false;
341 327
342 // Only allow HTTP URLs or HTTPS URLs for the same domain as the search 328 // Only allow HTTP URLs or HTTPS URLs for the same domain as the search
343 // provider. 329 // provider.
344 if ((current_page_url.scheme() != url::kHttpScheme) && 330 if ((current_page_url.scheme() != url::kHttpScheme) &&
345 ((current_page_url.scheme() != url::kHttpsScheme) || 331 ((current_page_url.scheme() != url::kHttpsScheme) ||
346 !net::registry_controlled_domains::SameDomainOrHost( 332 !net::registry_controlled_domains::SameDomainOrHost(
347 current_page_url, suggest_url, 333 current_page_url, suggest_url,
348 net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES))) 334 net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES)))
349 return false; 335 return false;
350 336
351 // Check field trials and settings allow sending the URL on suggest requests. 337 if (!delegate->TabSyncEnabledAndUnencrypted())
352 ProfileSyncService* service =
353 ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile);
354 sync_driver::SyncPrefs sync_prefs(profile->GetPrefs());
355 if (service == NULL ||
356 !service->IsSyncEnabledAndLoggedIn() ||
357 !sync_prefs.GetPreferredDataTypes(syncer::UserTypes()).Has(
358 syncer::PROXY_TABS) ||
359 service->GetEncryptedDataTypes().Has(syncer::SESSIONS))
360 return false; 338 return false;
361 339
362 return true; 340 return true;
363 } 341 }
364 342
365 void BaseSearchProvider::AddMatchToMap( 343 void BaseSearchProvider::AddMatchToMap(
366 const SearchSuggestionParser::SuggestResult& result, 344 const SearchSuggestionParser::SuggestResult& result,
367 const std::string& metadata, 345 const std::string& metadata,
368 int accepted_suggestion, 346 int accepted_suggestion,
369 bool mark_as_deletable, 347 bool mark_as_deletable,
370 bool in_keyword_mode, 348 bool in_keyword_mode,
371 MatchMap* map) { 349 MatchMap* map) {
372 AutocompleteMatch match = CreateSearchSuggestion( 350 AutocompleteMatch match = CreateSearchSuggestion(
373 this, GetInput(result.from_keyword_provider()), in_keyword_mode, result, 351 this, GetInput(result.from_keyword_provider()), in_keyword_mode, result,
374 GetTemplateURL(result.from_keyword_provider()), 352 GetTemplateURL(result.from_keyword_provider()),
375 template_url_service_->search_terms_data(), accepted_suggestion, 353 template_url_service_->search_terms_data(), accepted_suggestion,
376 ShouldAppendExtraParams(result)); 354 ShouldAppendExtraParams(result));
377 if (!match.destination_url.is_valid()) 355 if (!match.destination_url.is_valid())
378 return; 356 return;
379 match.search_terms_args->bookmark_bar_pinned = 357 match.search_terms_args->bookmark_bar_pinned = delegate_->ShowBookmarkBar();
380 profile_->GetPrefs()->GetBoolean(prefs::kShowBookmarkBar);
381 match.RecordAdditionalInfo(kRelevanceFromServerKey, 358 match.RecordAdditionalInfo(kRelevanceFromServerKey,
382 result.relevance_from_server() ? kTrue : kFalse); 359 result.relevance_from_server() ? kTrue : kFalse);
383 match.RecordAdditionalInfo(kShouldPrefetchKey, 360 match.RecordAdditionalInfo(kShouldPrefetchKey,
384 result.should_prefetch() ? kTrue : kFalse); 361 result.should_prefetch() ? kTrue : kFalse);
385 SetDeletionURL(result.deletion_url(), &match); 362 SetDeletionURL(result.deletion_url(), &match);
386 if (mark_as_deletable) 363 if (mark_as_deletable)
387 match.deletable = true; 364 match.deletable = true;
388 // Metadata is needed only for prefetching queries. 365 // Metadata is needed only for prefetching queries.
389 if (result.should_prefetch()) 366 if (result.should_prefetch())
390 match.RecordAdditionalInfo(kSuggestMetadataKey, metadata); 367 match.RecordAdditionalInfo(kSuggestMetadataKey, metadata);
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
440 } 417 }
441 } 418 }
442 419
443 bool BaseSearchProvider::ParseSuggestResults( 420 bool BaseSearchProvider::ParseSuggestResults(
444 const base::Value& root_val, 421 const base::Value& root_val,
445 int default_result_relevance, 422 int default_result_relevance,
446 bool is_keyword_result, 423 bool is_keyword_result,
447 SearchSuggestionParser::Results* results) { 424 SearchSuggestionParser::Results* results) {
448 if (!SearchSuggestionParser::ParseSuggestResults( 425 if (!SearchSuggestionParser::ParseSuggestResults(
449 root_val, GetInput(is_keyword_result), 426 root_val, GetInput(is_keyword_result),
450 ChromeAutocompleteSchemeClassifier(profile_), default_result_relevance, 427 delegate_->SchemeClassifier(), default_result_relevance,
451 profile_->GetPrefs()->GetString(prefs::kAcceptLanguages), 428 delegate_->AcceptLanguages(), is_keyword_result, results))
452 is_keyword_result, results))
453 return false; 429 return false;
454 430
455 BitmapFetcherService* image_service =
456 BitmapFetcherServiceFactory::GetForBrowserContext(profile_);
457 DCHECK(image_service);
458 for (std::vector<GURL>::const_iterator it = 431 for (std::vector<GURL>::const_iterator it =
459 results->answers_image_urls.begin(); 432 results->answers_image_urls.begin();
460 it != results->answers_image_urls.end(); ++it) 433 it != results->answers_image_urls.end(); ++it)
461 image_service->Prefetch(*it); 434 delegate_->PrefetchImage(*it);
462 435
463 field_trial_triggered_ |= results->field_trial_triggered; 436 field_trial_triggered_ |= results->field_trial_triggered;
464 field_trial_triggered_in_session_ |= results->field_trial_triggered; 437 field_trial_triggered_in_session_ |= results->field_trial_triggered;
465 return true; 438 return true;
466 } 439 }
467 440
468 void BaseSearchProvider::DeleteMatchFromMatches( 441 void BaseSearchProvider::DeleteMatchFromMatches(
469 const AutocompleteMatch& match) { 442 const AutocompleteMatch& match) {
470 for (ACMatches::iterator i(matches_.begin()); i != matches_.end(); ++i) { 443 for (ACMatches::iterator i(matches_.begin()); i != matches_.end(); ++i) {
471 // Find the desired match to delete by checking the type and contents. 444 // Find the desired match to delete by checking the type and contents.
472 // We can't check the destination URL, because the autocomplete controller 445 // We can't check the destination URL, because the autocomplete controller
473 // may have reformulated that. Not that while checking for matching 446 // may have reformulated that. Not that while checking for matching
474 // contents works for personalized suggestions, if more match types gain 447 // contents works for personalized suggestions, if more match types gain
475 // deletion support, this algorithm may need to be re-examined. 448 // deletion support, this algorithm may need to be re-examined.
476 if (i->contents == match.contents && i->type == match.type) { 449 if (i->contents == match.contents && i->type == match.type) {
477 matches_.erase(i); 450 matches_.erase(i);
478 break; 451 break;
479 } 452 }
480 } 453 }
481 } 454 }
482 455
483 void BaseSearchProvider::OnDeletionComplete( 456 void BaseSearchProvider::OnDeletionComplete(
484 bool success, SuggestionDeletionHandler* handler) { 457 bool success, SuggestionDeletionHandler* handler) {
485 RecordDeletionResult(success); 458 RecordDeletionResult(success);
486 SuggestionDeletionHandlers::iterator it = std::find( 459 SuggestionDeletionHandlers::iterator it = std::find(
487 deletion_handlers_.begin(), deletion_handlers_.end(), handler); 460 deletion_handlers_.begin(), deletion_handlers_.end(), handler);
488 DCHECK(it != deletion_handlers_.end()); 461 DCHECK(it != deletion_handlers_.end());
489 deletion_handlers_.erase(it); 462 deletion_handlers_.erase(it);
490 } 463 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698