OLD | NEW |
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 // Installs Autofill management functions on the |__gCrWeb| object. | 5 // Installs Autofill management functions on the |__gCrWeb| object. |
6 // | 6 // |
7 // It scans the DOM, extracting and storing forms and returns a JSON string | 7 // It scans the DOM, extracting and storing forms and returns a JSON string |
8 // representing an array of objects, each of which represents an Autofill form | 8 // representing an array of objects, each of which represents an Autofill form |
9 // with information about a form to be filled and/or submitted and it can be | 9 // with information about a form to be filled and/or submitted and it can be |
10 // translated to struct FormData | 10 // translated to struct FormData |
(...skipping 483 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
494 return; | 494 return; |
495 } | 495 } |
496 __gCrWeb.autofill.lastAutoFilledElement = activeElement; | 496 __gCrWeb.autofill.lastAutoFilledElement = activeElement; |
497 __gCrWeb.autofill.fillFormField(data, activeElement); | 497 __gCrWeb.autofill.fillFormField(data, activeElement); |
498 }; | 498 }; |
499 | 499 |
500 /** | 500 /** |
501 * Fills a number of fields in the same named form. | 501 * Fills a number of fields in the same named form. |
502 * | 502 * |
503 * @param {Object<AutofillFormData>} data The data to fill in. | 503 * @param {Object<AutofillFormData>} data The data to fill in. |
| 504 * @param {boolean} onlyFillEmpty Only fill empty fields. Otherwise fill all |
| 505 * fields. |
| 506 * @param {string} forceFillFieldName Named field will always be filled, |
| 507 * regardless of value of |onlyFillEmpty|. May be null. |
504 * @param {boolean} styleElements Apply Autofill CSS style to filled elements. | 508 * @param {boolean} styleElements Apply Autofill CSS style to filled elements. |
505 */ | 509 */ |
506 __gCrWeb.autofill['fillForm'] = function(data, styleElements) { | 510 __gCrWeb.autofill['fillForm'] = function(data, onlyFillEmpty, |
| 511 forceFillFieldName, styleElements) { |
507 // Inject CSS to style the autofilled elements with a yellow background. | 512 // Inject CSS to style the autofilled elements with a yellow background. |
508 if (styleElements && !__gCrWeb.autofill.styleInjected) { | 513 if (styleElements && !__gCrWeb.autofill.styleInjected) { |
509 var style = document.createElement('style'); | 514 var style = document.createElement('style'); |
510 style.textContent = '[chrome-autofilled] {' + | 515 style.textContent = '[chrome-autofilled] {' + |
511 'background-color:#FAFFBD !important;' + | 516 'background-color:#FAFFBD !important;' + |
512 'background-image:none !important;' + | 517 'background-image:none !important;' + |
513 'color:#000000 !important;' + | 518 'color:#000000 !important;' + |
514 '}'; | 519 '}'; |
515 document.head.appendChild(style); | 520 document.head.appendChild(style); |
516 __gCrWeb.autofill.styleInjected = true; | 521 __gCrWeb.autofill.styleInjected = true; |
517 } | 522 } |
518 | 523 |
519 // Remove Autofill styling when control element is edited. | 524 // Remove Autofill styling when control element is edited. |
520 var controlElementInputListener = function(evt) { | 525 var controlElementInputListener = function(evt) { |
521 evt.target.removeAttribute('chrome-autofilled'); | 526 evt.target.removeAttribute('chrome-autofilled'); |
| 527 evt.target.isAutofilled = false; |
522 evt.target.removeEventListener('input', controlElementInputListener); | 528 evt.target.removeEventListener('input', controlElementInputListener); |
523 }; | 529 }; |
524 | 530 |
525 var form = __gCrWeb.common.getFormElementFromIdentifier(data.formName); | 531 var form = __gCrWeb.common.getFormElementFromIdentifier(data.formName); |
526 var controlElements = __gCrWeb.common.getFormControlElements(form); | 532 var controlElements = __gCrWeb.common.getFormControlElements(form); |
527 for (var i = 0; i < controlElements.length; ++i) { | 533 for (var i = 0; i < controlElements.length; ++i) { |
528 var element = controlElements[i]; | 534 var element = controlElements[i]; |
529 if (!__gCrWeb.autofill.isAutofillableElement(element)) { | 535 if (!__gCrWeb.autofill.isAutofillableElement(element)) { |
530 continue; | 536 continue; |
531 } | 537 } |
532 var value = data.fields[__gCrWeb['common'].nameForAutofill(element)]; | 538 var fieldName = __gCrWeb['common'].nameForAutofill(element); |
| 539 |
| 540 // If directed, skip non-empty fields unless this is the forceFillFieldName |
| 541 // or it's a 'select-one' element. 'select-one' elements are always |
| 542 // autofilled even if non-empty; see |
| 543 // AutofillManager::FillOrPreviewDataModelForm(). |
| 544 if (onlyFillEmpty && element.value && element.value.length > 0 && |
| 545 !__gCrWeb.autofill.isSelectElement(element) && |
| 546 fieldName !== forceFillFieldName) { |
| 547 continue; |
| 548 } |
| 549 var value = data.fields[fieldName]; |
533 if (value) { | 550 if (value) { |
534 element.value = value; | 551 element.value = value; |
535 if (styleElements) { | 552 if (styleElements) { |
536 element.setAttribute('chrome-autofilled'); | 553 element.setAttribute('chrome-autofilled'); |
| 554 element.isAutofilled = true; |
537 element.addEventListener('input', controlElementInputListener); | 555 element.addEventListener('input', controlElementInputListener); |
538 } | 556 } |
539 } | 557 } |
540 } | 558 } |
541 | 559 |
542 // Remove Autofill styling when form receives 'reset' event. | 560 // Remove Autofill styling when form receives 'reset' event. |
543 // Individual control elements may be left with 'input' event listeners but | 561 // Individual control elements may be left with 'input' event listeners but |
544 // they are harmless. | 562 // they are harmless. |
545 if (styleElements) { | 563 if (styleElements) { |
546 var formResetListener = function(evt) { | 564 var formResetListener = function(evt) { |
547 var controlElements = __gCrWeb.common.getFormControlElements(evt.target); | 565 var controlElements = __gCrWeb.common.getFormControlElements(evt.target); |
548 for (var i = 0; i < controlElements.length; ++i) { | 566 for (var i = 0; i < controlElements.length; ++i) { |
549 controlElements[i].removeAttribute('chrome-autofilled'); | 567 controlElements[i].removeAttribute('chrome-autofilled'); |
| 568 controlElements[i].isAutofilled = false; |
550 } | 569 } |
551 evt.target.removeEventListener('reset', formResetListener); | 570 evt.target.removeEventListener('reset', formResetListener); |
552 }; | 571 }; |
553 | 572 |
554 form.addEventListener('reset', formResetListener); | 573 form.addEventListener('reset', formResetListener); |
555 } | 574 } |
556 }; | 575 }; |
557 | 576 |
558 /** | 577 /** |
559 * Dispatch an autocomplete event to the named form. | 578 * Dispatch an autocomplete event to the named form. |
(...skipping 1186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1746 continue; | 1765 continue; |
1747 } | 1766 } |
1748 var elementName = __gCrWeb['common'].nameForAutofill(element); | 1767 var elementName = __gCrWeb['common'].nameForAutofill(element); |
1749 var value = formData[elementName]; | 1768 var value = formData[elementName]; |
1750 if (value) { | 1769 if (value) { |
1751 element.placeholder = value; | 1770 element.placeholder = value; |
1752 } | 1771 } |
1753 } | 1772 } |
1754 } | 1773 } |
1755 }; | 1774 }; |
OLD | NEW |