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

Side by Side Diff: components/autofill/content/browser/autocheckout_manager.cc

Issue 23033016: Remove autocheckout code. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Even more deletes, and Ilya review. Created 7 years, 3 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "components/autofill/content/browser/autocheckout_manager.h"
6
7 #include "base/basictypes.h"
8 #include "base/bind.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "components/autofill/content/browser/autocheckout_request_manager.h"
11 #include "components/autofill/content/browser/autocheckout_statistic.h"
12 #include "components/autofill/content/browser/autocheckout_steps.h"
13 #include "components/autofill/core/browser/autofill_country.h"
14 #include "components/autofill/core/browser/autofill_field.h"
15 #include "components/autofill/core/browser/autofill_manager.h"
16 #include "components/autofill/core/browser/autofill_metrics.h"
17 #include "components/autofill/core/browser/autofill_profile.h"
18 #include "components/autofill/core/browser/autofill_type.h"
19 #include "components/autofill/core/browser/credit_card.h"
20 #include "components/autofill/core/browser/form_structure.h"
21 #include "components/autofill/core/common/autofill_messages.h"
22 #include "components/autofill/core/common/form_data.h"
23 #include "components/autofill/core/common/form_field_data.h"
24 #include "components/autofill/core/common/web_element_descriptor.h"
25 #include "content/public/browser/browser_context.h"
26 #include "content/public/browser/browser_thread.h"
27 #include "content/public/browser/render_view_host.h"
28 #include "content/public/browser/web_contents.h"
29 #include "net/cookies/cookie_options.h"
30 #include "net/cookies/cookie_store.h"
31 #include "net/url_request/url_request_context.h"
32 #include "net/url_request/url_request_context_getter.h"
33 #include "ui/gfx/rect.h"
34 #include "url/gurl.h"
35
36 using content::RenderViewHost;
37 using content::WebContents;
38
39 namespace autofill {
40
41 namespace {
42
43 const char kGoogleAccountsUrl[] = "https://accounts.google.com/";
44
45 // Build FormFieldData based on the supplied |autocomplete_attribute|. Will
46 // fill rest of properties with default values.
47 FormFieldData BuildField(const std::string& autocomplete_attribute) {
48 FormFieldData field;
49 field.name = base::string16();
50 field.value = base::string16();
51 field.autocomplete_attribute = autocomplete_attribute;
52 field.form_control_type = "text";
53 return field;
54 }
55
56 // Build Autocheckout specific form data to be consumed by
57 // AutofillDialogController to show the Autocheckout specific UI.
58 FormData BuildAutocheckoutFormData() {
59 FormData formdata;
60 formdata.fields.push_back(BuildField("email"));
61 formdata.fields.push_back(BuildField("cc-name"));
62 formdata.fields.push_back(BuildField("cc-number"));
63 formdata.fields.push_back(BuildField("cc-exp-month"));
64 formdata.fields.push_back(BuildField("cc-exp-year"));
65 formdata.fields.push_back(BuildField("cc-csc"));
66 formdata.fields.push_back(BuildField("billing address-line1"));
67 formdata.fields.push_back(BuildField("billing address-line2"));
68 formdata.fields.push_back(BuildField("billing locality"));
69 formdata.fields.push_back(BuildField("billing region"));
70 formdata.fields.push_back(BuildField("billing country"));
71 formdata.fields.push_back(BuildField("billing postal-code"));
72 formdata.fields.push_back(BuildField("billing tel"));
73 formdata.fields.push_back(BuildField("shipping name"));
74 formdata.fields.push_back(BuildField("shipping address-line1"));
75 formdata.fields.push_back(BuildField("shipping address-line2"));
76 formdata.fields.push_back(BuildField("shipping locality"));
77 formdata.fields.push_back(BuildField("shipping region"));
78 formdata.fields.push_back(BuildField("shipping country"));
79 formdata.fields.push_back(BuildField("shipping postal-code"));
80 formdata.fields.push_back(BuildField("shipping tel"));
81 return formdata;
82 }
83
84 AutofillMetrics::AutocheckoutBuyFlowMetric AutocheckoutStatusToUmaMetric(
85 AutocheckoutStatus status) {
86 switch (status) {
87 case SUCCESS:
88 return AutofillMetrics::AUTOCHECKOUT_BUY_FLOW_SUCCESS;
89 case MISSING_FIELDMAPPING:
90 return AutofillMetrics::AUTOCHECKOUT_BUY_FLOW_MISSING_FIELDMAPPING;
91 case MISSING_CLICK_ELEMENT_BEFORE_FORM_FILLING:
92 return AutofillMetrics::
93 AUTOCHECKOUT_BUY_FLOW_MISSING_CLICK_ELEMENT_BEFORE_FORM_FILLING;
94 case MISSING_CLICK_ELEMENT_AFTER_FORM_FILLING:
95 return AutofillMetrics::
96 AUTOCHECKOUT_BUY_FLOW_MISSING_CLICK_ELEMENT_AFTER_FORM_FILLING;
97 case MISSING_ADVANCE:
98 return AutofillMetrics::AUTOCHECKOUT_BUY_FLOW_MISSING_ADVANCE_ELEMENT;
99 case CANNOT_PROCEED:
100 return AutofillMetrics::AUTOCHECKOUT_BUY_FLOW_CANNOT_PROCEED;
101 case AUTOCHECKOUT_STATUS_NUM_STATUS:
102 NOTREACHED();
103 }
104
105 NOTREACHED();
106 return AutofillMetrics::NUM_AUTOCHECKOUT_BUY_FLOW_METRICS;
107 }
108
109 // Callback for retrieving Google Account cookies. |callback| is passed the
110 // retrieved cookies and posted back to the UI thread. |cookies| is any Google
111 // Account cookies.
112 void GetGoogleCookiesCallback(
113 const base::Callback<void(const std::string&)>& callback,
114 const std::string& cookies) {
115 content::BrowserThread::PostTask(content::BrowserThread::UI,
116 FROM_HERE,
117 base::Bind(callback, cookies));
118 }
119
120 // Gets Google Account cookies. Must be called on the IO thread.
121 // |request_context_getter| is a getter for the current request context.
122 // |callback| is called when retrieving cookies is completed.
123 void GetGoogleCookies(
124 scoped_refptr<net::URLRequestContextGetter> request_context_getter,
125 const base::Callback<void(const std::string&)>& callback) {
126 net::URLRequestContext* url_request_context =
127 request_context_getter->GetURLRequestContext();
128 if (!url_request_context)
129 return;
130
131 net::CookieStore* cookie_store = url_request_context->cookie_store();
132
133 base::Callback<void(const std::string&)> cookie_callback = base::Bind(
134 &GetGoogleCookiesCallback,
135 callback);
136
137 net::CookieOptions cookie_options;
138 cookie_options.set_include_httponly();
139 cookie_store->GetCookiesWithOptionsAsync(GURL(kGoogleAccountsUrl),
140 cookie_options,
141 cookie_callback);
142 }
143
144 bool IsBillingGroup(FieldTypeGroup group) {
145 return group == ADDRESS_BILLING ||
146 group == PHONE_BILLING ||
147 group == NAME_BILLING;
148 }
149
150 const char kTransactionIdNotSet[] = "transaction id not set";
151
152 } // namespace
153
154 AutocheckoutManager::AutocheckoutManager(AutofillManager* autofill_manager)
155 : autofill_manager_(autofill_manager),
156 metric_logger_(new AutofillMetrics),
157 should_show_bubble_(true),
158 is_autocheckout_bubble_showing_(false),
159 in_autocheckout_flow_(false),
160 should_preserve_dialog_(false),
161 google_transaction_id_(kTransactionIdNotSet),
162 weak_ptr_factory_(this) {}
163
164 AutocheckoutManager::~AutocheckoutManager() {
165 }
166
167 void AutocheckoutManager::FillForms() {
168 // |page_meta_data_| should have been set by OnLoadedPageMetaData.
169 DCHECK(page_meta_data_);
170
171 // Fill the forms on the page with data given by user.
172 std::vector<FormData> filled_forms;
173 const std::vector<FormStructure*>& form_structures =
174 autofill_manager_->GetFormStructures();
175 for (std::vector<FormStructure*>::const_iterator iter =
176 form_structures.begin(); iter != form_structures.end(); ++iter) {
177 FormStructure* form_structure = *iter;
178 form_structure->set_filled_by_autocheckout(true);
179 FormData form = form_structure->ToFormData();
180 DCHECK_EQ(form_structure->field_count(), form.fields.size());
181
182 for (size_t i = 0; i < form_structure->field_count(); ++i) {
183 const AutofillField* field = form_structure->field(i);
184 SetValue(*field, &form.fields[i]);
185 }
186
187 filled_forms.push_back(form);
188 }
189
190 // Send filled forms along with proceed descriptor to renderer.
191 RenderViewHost* host =
192 autofill_manager_->GetWebContents()->GetRenderViewHost();
193 if (!host)
194 return;
195
196 host->Send(new AutofillMsg_FillFormsAndClick(
197 host->GetRoutingID(),
198 filled_forms,
199 page_meta_data_->click_elements_before_form_fill,
200 page_meta_data_->click_elements_after_form_fill,
201 page_meta_data_->proceed_element_descriptor));
202 // Record time taken for navigating current page.
203 RecordTimeTaken(page_meta_data_->current_page_number);
204 }
205
206 void AutocheckoutManager::OnAutocheckoutPageCompleted(
207 AutocheckoutStatus status) {
208 if (!in_autocheckout_flow_)
209 return;
210
211 DVLOG(2) << "OnAutocheckoutPageCompleted, page_no: "
212 << page_meta_data_->current_page_number
213 << " status: "
214 << status;
215
216 DCHECK_NE(MISSING_FIELDMAPPING, status);
217
218 SetStepProgressForPage(
219 page_meta_data_->current_page_number,
220 (status == SUCCESS) ? AUTOCHECKOUT_STEP_COMPLETED :
221 AUTOCHECKOUT_STEP_FAILED);
222
223 if (page_meta_data_->IsEndOfAutofillableFlow() || status != SUCCESS)
224 EndAutocheckout(status);
225 }
226
227 void AutocheckoutManager::OnLoadedPageMetaData(
228 scoped_ptr<AutocheckoutPageMetaData> page_meta_data) {
229 scoped_ptr<AutocheckoutPageMetaData> old_meta_data = page_meta_data_.Pass();
230 page_meta_data_ = page_meta_data.Pass();
231
232 // If there is no click element in the last page, then it's the real last page
233 // of the flow, and the dialog will be closed when the page navigates.
234 // Otherwise, the dialog should be preserved for the page loaded by the click
235 // element on the last page of the flow.
236 // Note, |should_preserve_dialog_| has to be computed at this point because
237 // |in_autocheckout_flow_| may change after |OnLoadedPageMetaData| is called.
238 should_preserve_dialog_ = in_autocheckout_flow_ ||
239 (old_meta_data.get() &&
240 old_meta_data->IsEndOfAutofillableFlow() &&
241 old_meta_data->proceed_element_descriptor.retrieval_method !=
242 WebElementDescriptor::NONE);
243
244 // Don't log that the bubble could be displayed if the user entered an
245 // Autocheckout flow and sees the first page of the flow again due to an
246 // error.
247 if (IsStartOfAutofillableFlow() && !in_autocheckout_flow_) {
248 metric_logger_->LogAutocheckoutBubbleMetric(
249 AutofillMetrics::BUBBLE_COULD_BE_DISPLAYED);
250 }
251
252 // On the first page of an Autocheckout flow, when this function is called the
253 // user won't have opted into the flow yet.
254 if (!in_autocheckout_flow_)
255 return;
256
257 AutocheckoutStatus status = SUCCESS;
258
259 // Missing Autofill server results.
260 if (!page_meta_data_.get()) {
261 status = MISSING_FIELDMAPPING;
262 } else if (IsStartOfAutofillableFlow()) {
263 // Not possible unless Autocheckout failed to proceed.
264 status = CANNOT_PROCEED;
265 } else if (!page_meta_data_->IsInAutofillableFlow()) {
266 // Missing Autocheckout meta data in the Autofill server results.
267 status = MISSING_FIELDMAPPING;
268 } else if (page_meta_data_->current_page_number <=
269 old_meta_data->current_page_number) {
270 // Not possible unless Autocheckout failed to proceed.
271 status = CANNOT_PROCEED;
272 }
273
274 // Encountered an error during the Autocheckout flow, probably to
275 // do with a problem on the previous page.
276 if (status != SUCCESS) {
277 SetStepProgressForPage(old_meta_data->current_page_number,
278 AUTOCHECKOUT_STEP_FAILED);
279 EndAutocheckout(status);
280 return;
281 }
282
283 SetStepProgressForPage(page_meta_data_->current_page_number,
284 AUTOCHECKOUT_STEP_STARTED);
285
286 FillForms();
287 }
288
289 void AutocheckoutManager::OnFormsSeen() {
290 should_show_bubble_ = true;
291 }
292
293 bool AutocheckoutManager::ShouldIgnoreAjax() {
294 return in_autocheckout_flow_ && page_meta_data_->ignore_ajax;
295 }
296
297 void AutocheckoutManager::MaybeShowAutocheckoutBubble(
298 const GURL& frame_url,
299 const gfx::RectF& bounding_box) {
300 if (!should_show_bubble_ ||
301 is_autocheckout_bubble_showing_ ||
302 !IsStartOfAutofillableFlow())
303 return;
304
305 base::Callback<void(const std::string&)> callback = base::Bind(
306 &AutocheckoutManager::ShowAutocheckoutBubble,
307 weak_ptr_factory_.GetWeakPtr(),
308 frame_url,
309 bounding_box);
310
311 content::WebContents* web_contents = autofill_manager_->GetWebContents();
312 if (!web_contents)
313 return;
314
315 content::BrowserContext* browser_context = web_contents->GetBrowserContext();
316 if(!browser_context)
317 return;
318
319 scoped_refptr<net::URLRequestContextGetter> request_context =
320 scoped_refptr<net::URLRequestContextGetter>(
321 browser_context->GetRequestContext());
322
323 if (!request_context.get())
324 return;
325
326 base::Closure task = base::Bind(&GetGoogleCookies, request_context, callback);
327
328 content::BrowserThread::PostTask(content::BrowserThread::IO,
329 FROM_HERE,
330 task);
331 }
332
333 void AutocheckoutManager::ReturnAutocheckoutData(
334 const FormStructure* result,
335 const std::string& google_transaction_id) {
336 if (!result) {
337 // When user cancels the dialog, |result| is NULL.
338 // TODO(): add AutocheckoutStatus.USER_CANCELLED, and call
339 // EndAutocheckout(USER_CANCELLED) instead.
340 in_autocheckout_flow_ = false;
341 return;
342 }
343
344 latency_statistics_.clear();
345 last_step_completion_timestamp_ = base::TimeTicks().Now();
346 google_transaction_id_ = google_transaction_id;
347 in_autocheckout_flow_ = true;
348 should_preserve_dialog_ = true;
349 metric_logger_->LogAutocheckoutBuyFlowMetric(
350 AutofillMetrics::AUTOCHECKOUT_BUY_FLOW_STARTED);
351
352 profile_.reset(new AutofillProfile());
353 credit_card_.reset(new CreditCard());
354 billing_address_.reset(new AutofillProfile());
355
356 for (size_t i = 0; i < result->field_count(); ++i) {
357 const AutofillType& type = result->field(i)->Type();
358 const base::string16& value = result->field(i)->value;
359 ServerFieldType server_type = type.GetStorableType();
360 if (server_type == CREDIT_CARD_VERIFICATION_CODE) {
361 cvv_ = result->field(i)->value;
362 continue;
363 }
364 FieldTypeGroup group = type.group();
365 if (group == CREDIT_CARD) {
366 credit_card_->SetRawInfo(server_type, value);
367 // TODO(dgwallinga): Find a way of cleanly deprecating CREDIT_CARD_NAME.
368 // code.google.com/p/chromium/issues/detail?id=263498
369 if (server_type == CREDIT_CARD_NAME)
370 billing_address_->SetRawInfo(NAME_BILLING_FULL, value);
371 } else if (server_type == ADDRESS_HOME_COUNTRY) {
372 if (IsBillingGroup(group))
373 billing_address_->SetInfo(type, value, autofill_manager_->app_locale());
374 else
375 profile_->SetInfo(type, value, autofill_manager_->app_locale());
376 } else if (IsBillingGroup(group)) {
377 billing_address_->SetRawInfo(server_type, value);
378 } else {
379 profile_->SetRawInfo(server_type, value);
380 }
381 }
382
383 // Page types only available in first-page meta data, so save
384 // them for use later as we navigate.
385 page_types_ = page_meta_data_->page_types;
386 SetStepProgressForPage(page_meta_data_->current_page_number,
387 AUTOCHECKOUT_STEP_STARTED);
388
389 FillForms();
390 }
391
392 void AutocheckoutManager::set_metric_logger(
393 scoped_ptr<AutofillMetrics> metric_logger) {
394 metric_logger_ = metric_logger.Pass();
395 }
396
397 void AutocheckoutManager::MaybeShowAutocheckoutDialog(
398 const GURL& frame_url,
399 AutocheckoutBubbleState state) {
400 is_autocheckout_bubble_showing_ = false;
401
402 // User has taken action on the bubble, don't offer bubble again.
403 if (state != AUTOCHECKOUT_BUBBLE_IGNORED)
404 should_show_bubble_ = false;
405
406 if (state != AUTOCHECKOUT_BUBBLE_ACCEPTED)
407 return;
408
409 base::Callback<void(const FormStructure*, const std::string&)> callback =
410 base::Bind(&AutocheckoutManager::ReturnAutocheckoutData,
411 weak_ptr_factory_.GetWeakPtr());
412 autofill_manager_->ShowRequestAutocompleteDialog(BuildAutocheckoutFormData(),
413 frame_url,
414 DIALOG_TYPE_AUTOCHECKOUT,
415 callback);
416
417 for (std::map<int, std::vector<AutocheckoutStepType> >::const_iterator
418 it = page_meta_data_->page_types.begin();
419 it != page_meta_data_->page_types.end(); ++it) {
420 for (size_t i = 0; i < it->second.size(); ++i) {
421 autofill_manager_->delegate()->AddAutocheckoutStep(it->second[i]);
422 }
423 }
424 }
425
426 void AutocheckoutManager::ShowAutocheckoutBubble(
427 const GURL& frame_url,
428 const gfx::RectF& bounding_box,
429 const std::string& cookies) {
430 DCHECK(thread_checker_.CalledOnValidThread());
431
432 base::Callback<void(AutocheckoutBubbleState)> callback = base::Bind(
433 &AutocheckoutManager::MaybeShowAutocheckoutDialog,
434 weak_ptr_factory_.GetWeakPtr(),
435 frame_url);
436 is_autocheckout_bubble_showing_ =
437 autofill_manager_->delegate()->ShowAutocheckoutBubble(
438 bounding_box,
439 cookies.find("LSID") != std::string::npos,
440 callback);
441 }
442
443 bool AutocheckoutManager::IsStartOfAutofillableFlow() const {
444 return page_meta_data_ && page_meta_data_->IsStartOfAutofillableFlow();
445 }
446
447 bool AutocheckoutManager::IsInAutofillableFlow() const {
448 return page_meta_data_ && page_meta_data_->IsInAutofillableFlow();
449 }
450
451 void AutocheckoutManager::SetValue(const AutofillField& field,
452 FormFieldData* field_to_fill) {
453 // No-op if Autofill server doesn't know about the field.
454 if (field.server_type() == NO_SERVER_DATA)
455 return;
456
457 const AutofillType& type = field.Type();
458
459 ServerFieldType server_type = type.GetStorableType();
460 if (server_type == FIELD_WITH_DEFAULT_VALUE) {
461 // For a form with radio buttons, like:
462 // <form>
463 // <input type="radio" name="sex" value="male">Male<br>
464 // <input type="radio" name="sex" value="female">Female
465 // </form>
466 // If the default value specified at the server is "female", then
467 // Autofill server responds back with following field mappings
468 // (fieldtype: FIELD_WITH_DEFAULT_VALUE, value: "female")
469 // (fieldtype: FIELD_WITH_DEFAULT_VALUE, value: "female")
470 // Note that, the field mapping is repeated twice to respond to both the
471 // input elements with the same name/signature in the form.
472 //
473 // FIELD_WITH_DEFAULT_VALUE can also be used for selects, the correspondent
474 // example of the radio buttons example above is:
475 // <SELECT name="sex">
476 // <OPTION value="female">Female</OPTION>
477 // <OPTION value="male">Male</OPTION>
478 // </SELECT>
479 base::string16 default_value = UTF8ToUTF16(field.default_value());
480 if (field.is_checkable) {
481 // Mark the field checked if server says the default value of the field
482 // to be this field's value.
483 field_to_fill->is_checked = (field.value == default_value);
484 } else if (field.form_control_type == "select-one") {
485 field_to_fill->value = default_value;
486 } else {
487 // FIELD_WITH_DEFAULT_VALUE should not be used for other type of fields.
488 NOTREACHED();
489 }
490 return;
491 }
492
493 // Handle verification code directly.
494 if (server_type == CREDIT_CARD_VERIFICATION_CODE) {
495 field_to_fill->value = cvv_;
496 return;
497 }
498
499 if (type.group() == CREDIT_CARD) {
500 credit_card_->FillFormField(
501 field, 0, autofill_manager_->app_locale(), field_to_fill);
502 } else if (IsBillingGroup(type.group())) {
503 billing_address_->FillFormField(
504 field, 0, autofill_manager_->app_locale(), field_to_fill);
505 } else {
506 profile_->FillFormField(
507 field, 0, autofill_manager_->app_locale(), field_to_fill);
508 }
509 }
510
511 void AutocheckoutManager::SendAutocheckoutStatus(AutocheckoutStatus status) {
512 // To ensure stale data isn't being sent.
513 DCHECK_NE(kTransactionIdNotSet, google_transaction_id_);
514
515 AutocheckoutRequestManager::CreateForBrowserContext(
516 autofill_manager_->GetWebContents()->GetBrowserContext());
517 AutocheckoutRequestManager* autocheckout_request_manager =
518 AutocheckoutRequestManager::FromBrowserContext(
519 autofill_manager_->GetWebContents()->GetBrowserContext());
520 // It is assumed that the domain Autocheckout starts on does not change
521 // during the flow. If this proves to be incorrect, the |source_url| from
522 // AutofillDialogControllerImpl will need to be provided in its callback in
523 // addition to the Google transaction id.
524 autocheckout_request_manager->SendAutocheckoutStatus(
525 status,
526 autofill_manager_->GetWebContents()->GetURL(),
527 latency_statistics_,
528 google_transaction_id_);
529
530 // Log the result of this Autocheckout flow to UMA.
531 metric_logger_->LogAutocheckoutBuyFlowMetric(
532 AutocheckoutStatusToUmaMetric(status));
533
534 google_transaction_id_ = kTransactionIdNotSet;
535 }
536
537 void AutocheckoutManager::SetStepProgressForPage(
538 int page_number,
539 AutocheckoutStepStatus status) {
540 if (page_types_.count(page_number) == 1) {
541 for (size_t i = 0; i < page_types_[page_number].size(); ++i) {
542 autofill_manager_->delegate()->UpdateAutocheckoutStep(
543 page_types_[page_number][i], status);
544 }
545 }
546 }
547
548 void AutocheckoutManager::RecordTimeTaken(int page_number) {
549 AutocheckoutStatistic statistic;
550 statistic.page_number = page_number;
551 if (page_types_.count(page_number) == 1) {
552 for (size_t i = 0; i < page_types_[page_number].size(); ++i) {
553 statistic.steps.push_back(page_types_[page_number][i]);
554 }
555 }
556
557 statistic.time_taken =
558 base::TimeTicks().Now() - last_step_completion_timestamp_;
559 latency_statistics_.push_back(statistic);
560
561 // Reset timestamp.
562 last_step_completion_timestamp_ = base::TimeTicks().Now();
563 }
564
565 void AutocheckoutManager::EndAutocheckout(AutocheckoutStatus status) {
566 DCHECK(in_autocheckout_flow_);
567
568 DVLOG(2) << "EndAutocheckout at step: "
569 << page_meta_data_->current_page_number
570 << " with status: "
571 << status;
572
573 SendAutocheckoutStatus(status);
574 if (status == SUCCESS)
575 autofill_manager_->delegate()->OnAutocheckoutSuccess();
576 else
577 autofill_manager_->delegate()->OnAutocheckoutError();
578 in_autocheckout_flow_ = false;
579 }
580
581 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698