autofill_metrics.cc revision 2385ea399aae016c0806a4f9ef3c9cfe3d2a39df
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/core/browser/autofill_metrics.h" 6 7#include "base/logging.h" 8#include "base/metrics/histogram.h" 9#include "base/time/time.h" 10#include "components/autofill/core/browser/autofill_type.h" 11#include "components/autofill/core/browser/form_structure.h" 12#include "components/autofill/core/common/form_data.h" 13 14namespace autofill { 15 16namespace { 17 18// Server experiments we support. 19enum ServerExperiment { 20 NO_EXPERIMENT = 0, 21 UNKNOWN_EXPERIMENT, 22 ACCEPTANCE_RATIO_06, 23 ACCEPTANCE_RATIO_1, 24 ACCEPTANCE_RATIO_2, 25 ACCEPTANCE_RATIO_4, 26 ACCEPTANCE_RATIO_05_WINNER_LEAD_RATIO_15, 27 ACCEPTANCE_RATIO_05_WINNER_LEAD_RATIO_25, 28 ACCEPTANCE_RATIO_05_WINNER_LEAD_RATIO_15_MIN_FORM_SCORE_5, 29 TOOLBAR_DATA_ONLY, 30 ACCEPTANCE_RATIO_04_WINNER_LEAD_RATIO_3_MIN_FORM_SCORE_4, 31 NO_SERVER_RESPONSE, 32 PROBABILITY_PICKER_05, 33 PROBABILITY_PICKER_025, 34 PROBABILITY_PICKER_025_CC_THRESHOLD_03, 35 PROBABILITY_PICKER_025_CONTEXTUAL_CC_THRESHOLD_03, 36 PROBABILITY_PICKER_025_CONTEXTUAL_CC_THRESHOLD_03_WITH_FALLBACK, 37 PROBABILITY_PICKER_05_CC_NAME_THRESHOLD_03_EXPERIMENT_1, 38 NUM_SERVER_EXPERIMENTS 39}; 40 41enum FieldTypeGroupForMetrics { 42 AMBIGUOUS = 0, 43 NAME, 44 COMPANY, 45 ADDRESS_LINE_1, 46 ADDRESS_LINE_2, 47 ADDRESS_CITY, 48 ADDRESS_STATE, 49 ADDRESS_ZIP, 50 ADDRESS_COUNTRY, 51 PHONE, 52 FAX, // Deprecated. 53 EMAIL, 54 CREDIT_CARD_NAME, 55 CREDIT_CARD_NUMBER, 56 CREDIT_CARD_DATE, 57 CREDIT_CARD_TYPE, 58 NUM_FIELD_TYPE_GROUPS_FOR_METRICS 59}; 60 61// First, translates |field_type| to the corresponding logical |group| from 62// |FieldTypeGroupForMetrics|. Then, interpolates this with the given |metric|, 63// which should be in the range [0, |num_possible_metrics|). 64// Returns the interpolated index. 65// 66// The interpolation maps the pair (|group|, |metric|) to a single index, so 67// that all the indicies for a given group are adjacent. In particular, with 68// the groups {AMBIGUOUS, NAME, ...} combining with the metrics {UNKNOWN, MATCH, 69// MISMATCH}, we create this set of mapped indices: 70// { 71// AMBIGUOUS+UNKNOWN, 72// AMBIGUOUS+MATCH, 73// AMBIGUOUS+MISMATCH, 74// NAME+UNKNOWN, 75// NAME+MATCH, 76// NAME+MISMATCH, 77// ... 78// }. 79// 80// Clients must ensure that |field_type| is one of the types Chrome supports 81// natively, e.g. |field_type| must not be a billng address. 82int GetFieldTypeGroupMetric(const AutofillFieldType field_type, 83 const int metric, 84 const int num_possible_metrics) { 85 DCHECK_LT(metric, num_possible_metrics); 86 87 FieldTypeGroupForMetrics group; 88 switch (AutofillType(field_type).group()) { 89 case ::autofill::NO_GROUP: 90 group = AMBIGUOUS; 91 break; 92 93 case ::autofill::NAME: 94 group = NAME; 95 break; 96 97 case ::autofill::COMPANY: 98 group = COMPANY; 99 break; 100 101 case ::autofill::ADDRESS_HOME: 102 switch (field_type) { 103 case ADDRESS_HOME_LINE1: 104 group = ADDRESS_LINE_1; 105 break; 106 case ADDRESS_HOME_LINE2: 107 group = ADDRESS_LINE_2; 108 break; 109 case ADDRESS_HOME_CITY: 110 group = ADDRESS_CITY; 111 break; 112 case ADDRESS_HOME_STATE: 113 group = ADDRESS_STATE; 114 break; 115 case ADDRESS_HOME_ZIP: 116 group = ADDRESS_ZIP; 117 break; 118 case ADDRESS_HOME_COUNTRY: 119 group = ADDRESS_COUNTRY; 120 break; 121 default: 122 NOTREACHED(); 123 group = AMBIGUOUS; 124 } 125 break; 126 127 case ::autofill::EMAIL: 128 group = EMAIL; 129 break; 130 131 case ::autofill::PHONE_HOME: 132 group = PHONE; 133 break; 134 135 case ::autofill::CREDIT_CARD: 136 switch (field_type) { 137 case ::autofill::CREDIT_CARD_NAME: 138 group = CREDIT_CARD_NAME; 139 break; 140 case ::autofill::CREDIT_CARD_NUMBER: 141 group = CREDIT_CARD_NUMBER; 142 break; 143 case ::autofill::CREDIT_CARD_TYPE: 144 group = CREDIT_CARD_TYPE; 145 default: 146 group = CREDIT_CARD_DATE; 147 } 148 break; 149 150 default: 151 NOTREACHED(); 152 group = AMBIGUOUS; 153 } 154 155 // Interpolate the |metric| with the |group|, so that all metrics for a given 156 // |group| are adjacent. 157 return (group * num_possible_metrics) + metric; 158} 159 160// Returns the histogram prefix to use for reporting metrics for |dialog_type|. 161std::string GetPrefixForDialogType(autofill::DialogType dialog_type) { 162 switch (dialog_type) { 163 case autofill::DIALOG_TYPE_AUTOCHECKOUT: 164 return "Autocheckout"; 165 166 case autofill::DIALOG_TYPE_REQUEST_AUTOCOMPLETE: 167 return "RequestAutocomplete"; 168 } 169 170 NOTREACHED(); 171 return "UnknownDialogType"; 172} 173 174std::string WalletApiMetricToString( 175 AutofillMetrics::WalletApiCallMetric metric) { 176 switch (metric) { 177 case AutofillMetrics::ACCEPT_LEGAL_DOCUMENTS: 178 return "AcceptLegalDocuments"; 179 case AutofillMetrics::AUTHENTICATE_INSTRUMENT: 180 return "AuthenticateInstrument"; 181 case AutofillMetrics::GET_FULL_WALLET: 182 return "GetFullWallet"; 183 case AutofillMetrics::GET_WALLET_ITEMS: 184 return "GetWalletItems"; 185 case AutofillMetrics::SAVE_TO_WALLET: 186 return "SaveToWallet"; 187 case AutofillMetrics::SEND_STATUS: 188 return "SendStatus"; 189 case AutofillMetrics::UNKNOWN_API_CALL: 190 NOTREACHED(); 191 return "UnknownApiCall"; 192 } 193 194 NOTREACHED(); 195 return "UnknownApiCall"; 196} 197 198// A version of the UMA_HISTOGRAM_ENUMERATION macro that allows the |name| 199// to vary over the program's runtime. 200void LogUMAHistogramEnumeration(const std::string& name, 201 int sample, 202 int boundary_value) { 203 DCHECK_LT(sample, boundary_value); 204 205 // Note: This leaks memory, which is expected behavior. 206 base::HistogramBase* histogram = 207 base::LinearHistogram::FactoryGet( 208 name, 209 1, 210 boundary_value, 211 boundary_value + 1, 212 base::HistogramBase::kUmaTargetedHistogramFlag); 213 histogram->Add(sample); 214} 215 216// A version of the UMA_HISTOGRAM_TIMES macro that allows the |name| 217// to vary over the program's runtime. 218void LogUMAHistogramTimes(const std::string& name, 219 const base::TimeDelta& duration) { 220 // Note: This leaks memory, which is expected behavior. 221 base::HistogramBase* histogram = 222 base::Histogram::FactoryTimeGet( 223 name, 224 base::TimeDelta::FromMilliseconds(1), 225 base::TimeDelta::FromSeconds(10), 226 50, 227 base::HistogramBase::kUmaTargetedHistogramFlag); 228 histogram->AddTime(duration); 229} 230 231// A version of the UMA_HISTOGRAM_LONG_TIMES macro that allows the |name| 232// to vary over the program's runtime. 233void LogUMAHistogramLongTimes(const std::string& name, 234 const base::TimeDelta& duration) { 235 // Note: This leaks memory, which is expected behavior. 236 base::HistogramBase* histogram = 237 base::Histogram::FactoryTimeGet( 238 name, 239 base::TimeDelta::FromMilliseconds(1), 240 base::TimeDelta::FromHours(1), 241 50, 242 base::HistogramBase::kUmaTargetedHistogramFlag); 243 histogram->AddTime(duration); 244} 245 246// Logs a type quality metric. The primary histogram name is constructed based 247// on |base_name| and |experiment_id|. The field-specific histogram name also 248// factors in the |field_type|. Logs a sample of |metric|, which should be in 249// the range [0, |num_possible_metrics|). 250void LogTypeQualityMetric(const std::string& base_name, 251 const int metric, 252 const int num_possible_metrics, 253 const AutofillFieldType field_type, 254 const std::string& experiment_id) { 255 DCHECK_LT(metric, num_possible_metrics); 256 257 std::string histogram_name = base_name; 258 if (!experiment_id.empty()) 259 histogram_name += "_" + experiment_id; 260 LogUMAHistogramEnumeration(histogram_name, metric, num_possible_metrics); 261 262 std::string sub_histogram_name = base_name + ".ByFieldType"; 263 if (!experiment_id.empty()) 264 sub_histogram_name += "_" + experiment_id; 265 const int field_type_group_metric = 266 GetFieldTypeGroupMetric(field_type, metric, num_possible_metrics); 267 const int num_field_type_group_metrics = 268 num_possible_metrics * NUM_FIELD_TYPE_GROUPS_FOR_METRICS; 269 LogUMAHistogramEnumeration(sub_histogram_name, 270 field_type_group_metric, 271 num_field_type_group_metrics); 272} 273 274void LogServerExperimentId(const std::string& histogram_name, 275 const std::string& experiment_id) { 276 ServerExperiment metric = UNKNOWN_EXPERIMENT; 277 278 const std::string default_experiment_name = 279 FormStructure(FormData(), std::string()).server_experiment_id(); 280 if (experiment_id.empty()) 281 metric = NO_EXPERIMENT; 282 else if (experiment_id == "ar06") 283 metric = ACCEPTANCE_RATIO_06; 284 else if (experiment_id == "ar1") 285 metric = ACCEPTANCE_RATIO_1; 286 else if (experiment_id == "ar2") 287 metric = ACCEPTANCE_RATIO_2; 288 else if (experiment_id == "ar4") 289 metric = ACCEPTANCE_RATIO_4; 290 else if (experiment_id == "ar05wlr15") 291 metric = ACCEPTANCE_RATIO_05_WINNER_LEAD_RATIO_15; 292 else if (experiment_id == "ar05wlr25") 293 metric = ACCEPTANCE_RATIO_05_WINNER_LEAD_RATIO_25; 294 else if (experiment_id == "ar05wr15fs5") 295 metric = ACCEPTANCE_RATIO_05_WINNER_LEAD_RATIO_15_MIN_FORM_SCORE_5; 296 else if (experiment_id == "tbar1") 297 metric = TOOLBAR_DATA_ONLY; 298 else if (experiment_id == "ar04wr3fs4") 299 metric = ACCEPTANCE_RATIO_04_WINNER_LEAD_RATIO_3_MIN_FORM_SCORE_4; 300 else if (experiment_id == default_experiment_name) 301 metric = NO_SERVER_RESPONSE; 302 else if (experiment_id == "fp05") 303 metric = PROBABILITY_PICKER_05; 304 else if (experiment_id == "fp025") 305 metric = PROBABILITY_PICKER_025; 306 else if (experiment_id == "fp05cc03") 307 metric = PROBABILITY_PICKER_025_CC_THRESHOLD_03; 308 else if (experiment_id == "fp05cco03") 309 metric = PROBABILITY_PICKER_025_CONTEXTUAL_CC_THRESHOLD_03; 310 else if (experiment_id == "fp05cco03cstd") 311 metric = PROBABILITY_PICKER_025_CONTEXTUAL_CC_THRESHOLD_03_WITH_FALLBACK; 312 else if (experiment_id == "fp05cc03e1") 313 metric = PROBABILITY_PICKER_05_CC_NAME_THRESHOLD_03_EXPERIMENT_1; 314 315 DCHECK_LT(metric, NUM_SERVER_EXPERIMENTS); 316 LogUMAHistogramEnumeration(histogram_name, metric, NUM_SERVER_EXPERIMENTS); 317} 318 319} // namespace 320 321AutofillMetrics::AutofillMetrics() { 322} 323 324AutofillMetrics::~AutofillMetrics() { 325} 326 327void AutofillMetrics::LogAutocheckoutBubbleMetric(BubbleMetric metric) const { 328 DCHECK_LT(metric, NUM_BUBBLE_METRICS); 329 330 UMA_HISTOGRAM_ENUMERATION("Autocheckout.Bubble", metric, NUM_BUBBLE_METRICS); 331} 332 333void AutofillMetrics::LogAutocheckoutBuyFlowMetric( 334 AutocheckoutBuyFlowMetric metric) const { 335 DCHECK_LT(metric, NUM_AUTOCHECKOUT_BUY_FLOW_METRICS); 336 337 UMA_HISTOGRAM_ENUMERATION("Autocheckout.BuyFlow", metric, 338 NUM_AUTOCHECKOUT_BUY_FLOW_METRICS); 339} 340 341void AutofillMetrics::LogCreditCardInfoBarMetric(InfoBarMetric metric) const { 342 DCHECK_LT(metric, NUM_INFO_BAR_METRICS); 343 344 UMA_HISTOGRAM_ENUMERATION("Autofill.CreditCardInfoBar", metric, 345 NUM_INFO_BAR_METRICS); 346} 347 348void AutofillMetrics::LogDialogDismissalState( 349 autofill::DialogType dialog_type, 350 DialogDismissalState state) const { 351 std::string name = GetPrefixForDialogType(dialog_type) + ".DismissalState"; 352 LogUMAHistogramEnumeration(name, state, NUM_DIALOG_DISMISSAL_STATES); 353} 354 355void AutofillMetrics::LogDialogInitialUserState( 356 autofill::DialogType dialog_type, 357 DialogInitialUserStateMetric user_type) const { 358 std::string name = GetPrefixForDialogType(dialog_type) + ".InitialUserState"; 359 LogUMAHistogramEnumeration( 360 name, user_type, NUM_DIALOG_INITIAL_USER_STATE_METRICS); 361} 362 363void AutofillMetrics::LogDialogLatencyToShow( 364 autofill::DialogType dialog_type, 365 const base::TimeDelta& duration) const { 366 std::string name = 367 GetPrefixForDialogType(dialog_type) + ".UiLatencyToShow"; 368 LogUMAHistogramTimes(name, duration); 369} 370 371void AutofillMetrics::LogDialogPopupEvent(autofill::DialogType dialog_type, 372 DialogPopupEvent event) const { 373 std::string name = GetPrefixForDialogType(dialog_type) + ".PopupInDialog"; 374 LogUMAHistogramEnumeration(name, event, NUM_DIALOG_POPUP_EVENTS); 375} 376 377void AutofillMetrics::LogDialogSecurityMetric( 378 autofill::DialogType dialog_type, 379 DialogSecurityMetric metric) const { 380 std::string name = GetPrefixForDialogType(dialog_type) + ".Security"; 381 LogUMAHistogramEnumeration(name, metric, NUM_DIALOG_SECURITY_METRICS); 382} 383 384void AutofillMetrics::LogDialogUiDuration( 385 const base::TimeDelta& duration, 386 autofill::DialogType dialog_type, 387 DialogDismissalAction dismissal_action) const { 388 std::string prefix = GetPrefixForDialogType(dialog_type); 389 390 std::string suffix; 391 switch (dismissal_action) { 392 case DIALOG_ACCEPTED: 393 suffix = "Submit"; 394 break; 395 396 case DIALOG_CANCELED: 397 suffix = "Cancel"; 398 break; 399 } 400 401 LogUMAHistogramLongTimes(prefix + ".UiDuration", duration); 402 LogUMAHistogramLongTimes(prefix + ".UiDuration." + suffix, duration); 403} 404 405void AutofillMetrics::LogDialogUiEvent(autofill::DialogType dialog_type, 406 DialogUiEvent event) const { 407 std::string name = GetPrefixForDialogType(dialog_type) + ".UiEvents"; 408 LogUMAHistogramEnumeration(name, event, NUM_DIALOG_UI_EVENTS); 409} 410 411void AutofillMetrics::LogWalletErrorMetric(autofill::DialogType dialog_type, 412 WalletErrorMetric metric) const { 413 std::string name = GetPrefixForDialogType(dialog_type) + ".WalletErrors"; 414 LogUMAHistogramEnumeration(name, metric, NUM_WALLET_ERROR_METRICS); 415} 416 417void AutofillMetrics::LogWalletApiCallDuration( 418 WalletApiCallMetric metric, 419 const base::TimeDelta& duration) const { 420 LogUMAHistogramTimes("Wallet.ApiCallDuration." + 421 WalletApiMetricToString(metric), duration); 422} 423 424void AutofillMetrics::LogWalletRequiredActionMetric( 425 autofill::DialogType dialog_type, 426 WalletRequiredActionMetric required_action) const { 427 std::string name = 428 GetPrefixForDialogType(dialog_type) + ".WalletRequiredActions"; 429 LogUMAHistogramEnumeration( 430 name, required_action, NUM_WALLET_REQUIRED_ACTIONS); 431} 432 433void AutofillMetrics::LogAutocheckoutDuration( 434 const base::TimeDelta& duration, 435 AutocheckoutCompletionStatus status) const { 436 std::string suffix; 437 switch (status) { 438 case AUTOCHECKOUT_CANCELLED: 439 suffix = "Cancelled"; 440 break; 441 442 case AUTOCHECKOUT_FAILED: 443 suffix = "Failed"; 444 break; 445 446 case AUTOCHECKOUT_SUCCEEDED: 447 suffix = "Succeeded"; 448 break; 449 } 450 451 LogUMAHistogramLongTimes("Autocheckout.FlowDuration", duration); 452 LogUMAHistogramLongTimes("Autocheckout.FlowDuration." + suffix, duration); 453} 454 455void AutofillMetrics::LogAutocheckoutWhitelistDownloadDuration( 456 const base::TimeDelta& duration, 457 AutocheckoutWhitelistDownloadStatus status) const { 458 std::string suffix; 459 switch (status) { 460 case AUTOCHECKOUT_WHITELIST_DOWNLOAD_FAILED: 461 suffix = "Failed"; 462 break; 463 464 case AUTOCHECKOUT_WHITELIST_DOWNLOAD_SUCCEEDED: 465 suffix = "Succeeded"; 466 break; 467 } 468 469 LogUMAHistogramTimes("Autocheckout.WhitelistDownloadDuration", duration); 470 LogUMAHistogramTimes( 471 "Autocheckout.WhitelistDownloadDuration." + suffix, duration); 472} 473 474void AutofillMetrics::LogDeveloperEngagementMetric( 475 DeveloperEngagementMetric metric) const { 476 DCHECK_LT(metric, NUM_DEVELOPER_ENGAGEMENT_METRICS); 477 478 UMA_HISTOGRAM_ENUMERATION("Autofill.DeveloperEngagement", metric, 479 NUM_DEVELOPER_ENGAGEMENT_METRICS); 480} 481 482void AutofillMetrics::LogHeuristicTypePrediction( 483 FieldTypeQualityMetric metric, 484 AutofillFieldType field_type, 485 const std::string& experiment_id) const { 486 LogTypeQualityMetric("Autofill.Quality.HeuristicType", 487 metric, NUM_FIELD_TYPE_QUALITY_METRICS, 488 field_type, experiment_id); 489} 490 491void AutofillMetrics::LogOverallTypePrediction( 492 FieldTypeQualityMetric metric, 493 AutofillFieldType field_type, 494 const std::string& experiment_id) const { 495 LogTypeQualityMetric("Autofill.Quality.PredictedType", 496 metric, NUM_FIELD_TYPE_QUALITY_METRICS, 497 field_type, experiment_id); 498} 499 500void AutofillMetrics::LogServerTypePrediction( 501 FieldTypeQualityMetric metric, 502 AutofillFieldType field_type, 503 const std::string& experiment_id) const { 504 LogTypeQualityMetric("Autofill.Quality.ServerType", 505 metric, NUM_FIELD_TYPE_QUALITY_METRICS, 506 field_type, experiment_id); 507} 508 509void AutofillMetrics::LogQualityMetric(QualityMetric metric, 510 const std::string& experiment_id) const { 511 DCHECK_LT(metric, NUM_QUALITY_METRICS); 512 513 std::string histogram_name = "Autofill.Quality"; 514 if (!experiment_id.empty()) 515 histogram_name += "_" + experiment_id; 516 517 LogUMAHistogramEnumeration(histogram_name, metric, NUM_QUALITY_METRICS); 518} 519 520void AutofillMetrics::LogServerQueryMetric(ServerQueryMetric metric) const { 521 DCHECK_LT(metric, NUM_SERVER_QUERY_METRICS); 522 523 UMA_HISTOGRAM_ENUMERATION("Autofill.ServerQueryResponse", metric, 524 NUM_SERVER_QUERY_METRICS); 525} 526 527void AutofillMetrics::LogUserHappinessMetric(UserHappinessMetric metric) const { 528 DCHECK_LT(metric, NUM_USER_HAPPINESS_METRICS); 529 530 UMA_HISTOGRAM_ENUMERATION("Autofill.UserHappiness", metric, 531 NUM_USER_HAPPINESS_METRICS); 532} 533 534void AutofillMetrics::LogFormFillDurationFromLoadWithAutofill( 535 const base::TimeDelta& duration) const { 536 UMA_HISTOGRAM_CUSTOM_TIMES("Autofill.FillDuration.FromLoad.WithAutofill", 537 duration, 538 base::TimeDelta::FromMilliseconds(100), 539 base::TimeDelta::FromMinutes(10), 540 50); 541} 542 543void AutofillMetrics::LogFormFillDurationFromLoadWithoutAutofill( 544 const base::TimeDelta& duration) const { 545 UMA_HISTOGRAM_CUSTOM_TIMES("Autofill.FillDuration.FromLoad.WithoutAutofill", 546 duration, 547 base::TimeDelta::FromMilliseconds(100), 548 base::TimeDelta::FromMinutes(10), 549 50); 550} 551 552void AutofillMetrics::LogFormFillDurationFromInteractionWithAutofill( 553 const base::TimeDelta& duration) const { 554 UMA_HISTOGRAM_CUSTOM_TIMES( 555 "Autofill.FillDuration.FromInteraction.WithAutofill", 556 duration, 557 base::TimeDelta::FromMilliseconds(100), 558 base::TimeDelta::FromMinutes(10), 559 50); 560} 561 562void AutofillMetrics::LogFormFillDurationFromInteractionWithoutAutofill( 563 const base::TimeDelta& duration) const { 564 UMA_HISTOGRAM_CUSTOM_TIMES( 565 "Autofill.FillDuration.FromInteraction.WithoutAutofill", 566 duration, 567 base::TimeDelta::FromMilliseconds(100), 568 base::TimeDelta::FromMinutes(10), 569 50); 570} 571 572void AutofillMetrics::LogIsAutofillEnabledAtStartup(bool enabled) const { 573 UMA_HISTOGRAM_BOOLEAN("Autofill.IsEnabled.Startup", enabled); 574} 575 576void AutofillMetrics::LogIsAutofillEnabledAtPageLoad(bool enabled) const { 577 UMA_HISTOGRAM_BOOLEAN("Autofill.IsEnabled.PageLoad", enabled); 578} 579 580void AutofillMetrics::LogStoredProfileCount(size_t num_profiles) const { 581 UMA_HISTOGRAM_COUNTS("Autofill.StoredProfileCount", num_profiles); 582} 583 584void AutofillMetrics::LogAddressSuggestionsCount(size_t num_suggestions) const { 585 UMA_HISTOGRAM_COUNTS("Autofill.AddressSuggestionsCount", num_suggestions); 586} 587 588void AutofillMetrics::LogServerExperimentIdForQuery( 589 const std::string& experiment_id) const { 590 LogServerExperimentId("Autofill.ServerExperimentId.Query", experiment_id); 591} 592 593void AutofillMetrics::LogServerExperimentIdForUpload( 594 const std::string& experiment_id) const { 595 LogServerExperimentId("Autofill.ServerExperimentId.Upload", experiment_id); 596} 597 598} // namespace autofill 599