| Index: components/autofill/content/renderer/password_autofill_agent.cc
 | 
| diff --git a/components/autofill/content/renderer/password_autofill_agent.cc b/components/autofill/content/renderer/password_autofill_agent.cc
 | 
| index 93dbdd5cf69c6d6345cf9becd3108d00e4d851b4..4e910ff869584c763fd7cbd858092794336227e9 100644
 | 
| --- a/components/autofill/content/renderer/password_autofill_agent.cc
 | 
| +++ b/components/autofill/content/renderer/password_autofill_agent.cc
 | 
| @@ -13,6 +13,7 @@
 | 
|  #include "base/bind.h"
 | 
|  #include "base/i18n/case_conversion.h"
 | 
|  #include "base/memory/linked_ptr.h"
 | 
| +#include "base/memory/ptr_util.h"
 | 
|  #include "base/message_loop/message_loop.h"
 | 
|  #include "base/metrics/histogram_macros.h"
 | 
|  #include "base/strings/utf_string_conversions.h"
 | 
| @@ -24,7 +25,6 @@
 | 
|  #include "components/autofill/core/common/autofill_constants.h"
 | 
|  #include "components/autofill/core/common/autofill_util.h"
 | 
|  #include "components/autofill/core/common/form_field_data.h"
 | 
| -#include "components/autofill/core/common/password_form.h"
 | 
|  #include "components/autofill/core/common/password_form_fill_data.h"
 | 
|  #include "content/public/renderer/document_state.h"
 | 
|  #include "content/public/renderer/navigation_state.h"
 | 
| @@ -349,19 +349,42 @@ bool CanShowSuggestion(const PasswordFormFillData& fill_data,
 | 
|    return false;
 | 
|  }
 | 
|  
 | 
| +// Updates the value (i.e. the pair of elements's value |value| and field
 | 
| +// properties |added_flags|) associated with the key |element| in
 | 
| +// |field_value_and_properties_map|.
 | 
| +// Flags in |added_flags| are added with bitwise OR operation.
 | 
| +// If |value| is null, the value is neither updated nor added.
 | 
| +void UpdateFieldValueAndPropertiesMaskMap(
 | 
| +    const blink::WebFormControlElement& element,
 | 
| +    const base::string16* value,
 | 
| +    FieldPropertiesMask added_flags,
 | 
| +    FieldValueAndPropertiesMaskMap* field_value_and_properties_map) {
 | 
| +  FieldValueAndPropertiesMaskMap::iterator it =
 | 
| +      field_value_and_properties_map->find(element);
 | 
| +  if (it != field_value_and_properties_map->end()) {
 | 
| +    if (value)
 | 
| +      it->second.first.reset(new base::string16(*value));
 | 
| +    it->second.second |= added_flags;
 | 
| +  } else {
 | 
| +    (*field_value_and_properties_map)[element] = std::make_pair(
 | 
| +        value ? base::WrapUnique(new base::string16(*value)) : nullptr,
 | 
| +        added_flags);
 | 
| +  }
 | 
| +}
 | 
| +
 | 
|  // This function attempts to fill |username_element| and |password_element|
 | 
|  // with values from |fill_data|. The |password_element| will only have the
 | 
|  // suggestedValue set, and will be registered for copying that to the real
 | 
|  // value through |registration_callback|. If a match is found, return true and
 | 
| -// |nonscript_modified_values| will be modified with the autofilled credentials.
 | 
| +// |field_value_and_properties_map| will be modified with the autofilled
 | 
| +// credentials and |FieldPropertiesFlags::AUTOFILLED| flag.
 | 
|  bool FillUserNameAndPassword(
 | 
|      blink::WebInputElement* username_element,
 | 
|      blink::WebInputElement* password_element,
 | 
|      const PasswordFormFillData& fill_data,
 | 
|      bool exact_username_match,
 | 
|      bool set_selection,
 | 
| -    std::map<const blink::WebInputElement, blink::WebString>*
 | 
| -        nonscript_modified_values,
 | 
| +    FieldValueAndPropertiesMaskMap* field_value_and_properties_map,
 | 
|      base::Callback<void(blink::WebInputElement*)> registration_callback,
 | 
|      RendererSavePasswordProgressLogger* logger) {
 | 
|    if (logger)
 | 
| @@ -428,7 +451,9 @@ bool FillUserNameAndPassword(
 | 
|        IsElementAutocompletable(*username_element)) {
 | 
|      // TODO(crbug.com/507714): Why not setSuggestedValue?
 | 
|      username_element->setValue(username, true);
 | 
| -    (*nonscript_modified_values)[*username_element] = username;
 | 
| +    UpdateFieldValueAndPropertiesMaskMap(*username_element, &username,
 | 
| +                                         FieldPropertiesFlags::AUTOFILLED,
 | 
| +                                         field_value_and_properties_map);
 | 
|      username_element->setAutofilled(true);
 | 
|      if (logger)
 | 
|        logger->LogElementName(Logger::STRING_USERNAME_FILLED, *username_element);
 | 
| @@ -446,7 +471,9 @@ bool FillUserNameAndPassword(
 | 
|    // sure that we do not fill in the DOM with a password until we believe the
 | 
|    // user is intentionally interacting with the page.
 | 
|    password_element->setSuggestedValue(password);
 | 
| -  (*nonscript_modified_values)[*password_element] = password;
 | 
| +  UpdateFieldValueAndPropertiesMaskMap(*password_element, &password,
 | 
| +                                       FieldPropertiesFlags::AUTOFILLED,
 | 
| +                                       field_value_and_properties_map);
 | 
|    registration_callback.Run(password_element);
 | 
|  
 | 
|    password_element->setAutofilled(true);
 | 
| @@ -467,8 +494,7 @@ bool FillFormOnPasswordReceived(
 | 
|      const PasswordFormFillData& fill_data,
 | 
|      blink::WebInputElement username_element,
 | 
|      blink::WebInputElement password_element,
 | 
| -    std::map<const blink::WebInputElement, blink::WebString>*
 | 
| -        nonscript_modified_values,
 | 
| +    FieldValueAndPropertiesMaskMap* field_value_and_properties_map,
 | 
|      base::Callback<void(blink::WebInputElement*)> registration_callback,
 | 
|      RendererSavePasswordProgressLogger* logger) {
 | 
|    // Do not fill if the password field is in a chain of iframes not having
 | 
| @@ -527,7 +553,7 @@ bool FillFormOnPasswordReceived(
 | 
|    return FillUserNameAndPassword(
 | 
|        &username_element, &password_element, fill_data,
 | 
|        true /* exact_username_match */, false /* set_selection */,
 | 
| -      nonscript_modified_values, registration_callback, logger);
 | 
| +      field_value_and_properties_map, registration_callback, logger);
 | 
|  }
 | 
|  
 | 
|  // Takes a |map| with pointers as keys and linked_ptr as values, and returns
 | 
| @@ -625,7 +651,7 @@ bool PasswordAutofillAgent::TextFieldDidEndEditing(
 | 
|    // Do not set selection when ending an editing session, otherwise it can
 | 
|    // mess with focus.
 | 
|    FillUserNameAndPassword(&username, &password, fill_data, true, false,
 | 
| -                          &nonscript_modified_values_,
 | 
| +                          &field_value_and_properties_map_,
 | 
|                            base::Bind(&PasswordValueGatekeeper::RegisterElement,
 | 
|                                       base::Unretained(&gatekeeper_)),
 | 
|                            nullptr);
 | 
| @@ -656,8 +682,12 @@ void PasswordAutofillAgent::UpdateStateForTextChange(
 | 
|    // TODO(vabr): Get a mutable argument instead. http://crbug.com/397083
 | 
|    blink::WebInputElement mutable_element = element;  // We need a non-const.
 | 
|  
 | 
| -  if (element.isTextField())
 | 
| -    nonscript_modified_values_[element] = element.value();
 | 
| +  if (element.isTextField()) {
 | 
| +    const base::string16 element_value = element.value();
 | 
| +    UpdateFieldValueAndPropertiesMaskMap(element, &element_value,
 | 
| +                                         FieldPropertiesFlags::USER_TYPED,
 | 
| +                                         &field_value_and_properties_map_);
 | 
| +  }
 | 
|  
 | 
|    blink::WebFrame* const element_frame = element.document().frame();
 | 
|    // The element's frame might have been detached in the meantime (see
 | 
| @@ -677,10 +707,10 @@ void PasswordAutofillAgent::UpdateStateForTextChange(
 | 
|    std::unique_ptr<PasswordForm> password_form;
 | 
|    if (element.form().isNull()) {
 | 
|      password_form = CreatePasswordFormFromUnownedInputElements(
 | 
| -        *element_frame, &nonscript_modified_values_, &form_predictions_);
 | 
| +        *element_frame, &field_value_and_properties_map_, &form_predictions_);
 | 
|    } else {
 | 
|      password_form = CreatePasswordFormFromWebForm(
 | 
| -        element.form(), &nonscript_modified_values_, &form_predictions_);
 | 
| +        element.form(), &field_value_and_properties_map_, &form_predictions_);
 | 
|    }
 | 
|    ProvisionallySavePassword(std::move(password_form), RESTRICTION_NONE);
 | 
|  
 | 
| @@ -723,12 +753,18 @@ bool PasswordAutofillAgent::FillSuggestion(
 | 
|    } else if (!username_element.isNull()) {
 | 
|      username_element.setValue(username, true);
 | 
|      username_element.setAutofilled(true);
 | 
| -    nonscript_modified_values_[username_element] = username;
 | 
| +    const base::string16 username_value = username;
 | 
| +    UpdateFieldValueAndPropertiesMaskMap(username_element, &username_value,
 | 
| +                                         FieldPropertiesFlags::AUTOFILLED,
 | 
| +                                         &field_value_and_properties_map_);
 | 
|    }
 | 
|  
 | 
|    password_element.setValue(password, true);
 | 
|    password_element.setAutofilled(true);
 | 
| -  nonscript_modified_values_[password_element] = password;
 | 
| +  const base::string16 password_value = password;
 | 
| +  UpdateFieldValueAndPropertiesMaskMap(password_element, &password_value,
 | 
| +                                       FieldPropertiesFlags::AUTOFILLED,
 | 
| +                                       &field_value_and_properties_map_);
 | 
|  
 | 
|    blink::WebInputElement mutable_filled_element = *element;
 | 
|    mutable_filled_element.setSelectionRange(element->value().length(),
 | 
| @@ -1105,7 +1141,7 @@ void PasswordAutofillAgent::WillSendSubmitEvent(
 | 
|    // Had the user cleared the password, |provisionally_saved_form_| would
 | 
|    // already have been updated in TextDidChangeInTextField.
 | 
|    std::unique_ptr<PasswordForm> password_form = CreatePasswordFormFromWebForm(
 | 
| -      form, &nonscript_modified_values_, &form_predictions_);
 | 
| +      form, &field_value_and_properties_map_, &form_predictions_);
 | 
|    ProvisionallySavePassword(std::move(password_form),
 | 
|                              RESTRICTION_NON_EMPTY_PASSWORD);
 | 
|  }
 | 
| @@ -1119,7 +1155,7 @@ void PasswordAutofillAgent::WillSubmitForm(const blink::WebFormElement& form) {
 | 
|    }
 | 
|  
 | 
|    std::unique_ptr<PasswordForm> submitted_form = CreatePasswordFormFromWebForm(
 | 
| -      form, &nonscript_modified_values_, &form_predictions_);
 | 
| +      form, &field_value_and_properties_map_, &form_predictions_);
 | 
|  
 | 
|    // If there is a provisionally saved password, copy over the previous
 | 
|    // password value so we get the user's typed password, not the value that
 | 
| @@ -1210,13 +1246,13 @@ void PasswordAutofillAgent::DidStartProvisionalLoad() {
 | 
|                        form_element);
 | 
|          }
 | 
|          possible_submitted_forms.push_back(CreatePasswordFormFromWebForm(
 | 
| -            form_element, &nonscript_modified_values_, &form_predictions_));
 | 
| +            form_element, &field_value_and_properties_map_,
 | 
| +            &form_predictions_));
 | 
|        }
 | 
|  
 | 
|        possible_submitted_forms.push_back(
 | 
|            CreatePasswordFormFromUnownedInputElements(
 | 
| -              *render_frame()->GetWebFrame(),
 | 
| -              &nonscript_modified_values_,
 | 
| +              *render_frame()->GetWebFrame(), &field_value_and_properties_map_,
 | 
|                &form_predictions_));
 | 
|  
 | 
|        for (const PasswordForm* password_form : possible_submitted_forms) {
 | 
| @@ -1268,7 +1304,7 @@ void PasswordAutofillAgent::OnFillPasswordForm(
 | 
|              : web_input_to_password_info_[element].password_field;
 | 
|      FillFormOnPasswordReceived(
 | 
|          form_data, username_element, password_element,
 | 
| -        &nonscript_modified_values_,
 | 
| +        &field_value_and_properties_map_,
 | 
|          base::Bind(&PasswordValueGatekeeper::RegisterElement,
 | 
|                     base::Unretained(&gatekeeper_)),
 | 
|          logger.get());
 | 
| @@ -1356,6 +1392,19 @@ void PasswordAutofillAgent::GetFillableElementFromFormData(
 | 
|    }
 | 
|  }
 | 
|  
 | 
| +void PasswordAutofillAgent::FocusedNodeHasChanged(const blink::WebNode& node) {
 | 
| +  if (node.isNull() || !node.isElementNode())
 | 
| +    return;
 | 
| +  const blink::WebElement web_element = node.toConst<blink::WebElement>();
 | 
| +  if (!web_element.isFormControlElement())
 | 
| +    return;
 | 
| +  const blink::WebFormControlElement control_element =
 | 
| +      web_element.toConst<blink::WebFormControlElement>();
 | 
| +  UpdateFieldValueAndPropertiesMaskMap(control_element, nullptr,
 | 
| +                                       FieldPropertiesFlags::HAD_FOCUS,
 | 
| +                                       &field_value_and_properties_map_);
 | 
| +}
 | 
| +
 | 
|  void PasswordAutofillAgent::OnSetLoggingState(bool active) {
 | 
|    logging_state_active_ = active;
 | 
|  }
 | 
| @@ -1375,11 +1424,11 @@ void PasswordAutofillAgent::OnFindFocusedPasswordForm() {
 | 
|      if (input.isPasswordField() && !input.form().isNull()) {
 | 
|        if (!input.form().isNull()) {
 | 
|          password_form = CreatePasswordFormFromWebForm(
 | 
| -            input.form(), &nonscript_modified_values_, &form_predictions_);
 | 
| +            input.form(), &field_value_and_properties_map_, &form_predictions_);
 | 
|        } else {
 | 
|          password_form = CreatePasswordFormFromUnownedInputElements(
 | 
| -            *render_frame()->GetWebFrame(),
 | 
| -            &nonscript_modified_values_, &form_predictions_);
 | 
| +            *render_frame()->GetWebFrame(), &field_value_and_properties_map_,
 | 
| +            &form_predictions_);
 | 
|          // Only try to use this form if |input| is one of the password elements
 | 
|          // for |password_form|.
 | 
|          if (password_form->password_element != input.nameForAutofill() &&
 | 
| @@ -1448,7 +1497,7 @@ void PasswordAutofillAgent::FrameClosing() {
 | 
|    }
 | 
|    web_input_to_password_info_.clear();
 | 
|    provisionally_saved_form_.reset();
 | 
| -  nonscript_modified_values_.clear();
 | 
| +  field_value_and_properties_map_.clear();
 | 
|  }
 | 
|  
 | 
|  void PasswordAutofillAgent::ClearPreview(
 | 
| 
 |