fd52df402f4af45b7093dd304339c83e79794f98
[platform/framework/web/crosswalk.git] / src / components / autofill / content / renderer / password_autofill_agent.cc
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/renderer/password_autofill_agent.h"
6
7 #include "base/bind.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/metrics/histogram.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "components/autofill/content/common/autofill_messages.h"
13 #include "components/autofill/content/renderer/form_autofill_util.h"
14 #include "components/autofill/content/renderer/password_form_conversion_utils.h"
15 #include "components/autofill/content/renderer/renderer_save_password_progress_logger.h"
16 #include "components/autofill/core/common/form_field_data.h"
17 #include "components/autofill/core/common/password_autofill_util.h"
18 #include "components/autofill/core/common/password_form.h"
19 #include "components/autofill/core/common/password_form_fill_data.h"
20 #include "content/public/common/page_transition_types.h"
21 #include "content/public/renderer/document_state.h"
22 #include "content/public/renderer/navigation_state.h"
23 #include "content/public/renderer/render_view.h"
24 #include "third_party/WebKit/public/platform/WebVector.h"
25 #include "third_party/WebKit/public/web/WebAutofillClient.h"
26 #include "third_party/WebKit/public/web/WebDocument.h"
27 #include "third_party/WebKit/public/web/WebElement.h"
28 #include "third_party/WebKit/public/web/WebFormElement.h"
29 #include "third_party/WebKit/public/web/WebInputEvent.h"
30 #include "third_party/WebKit/public/web/WebLocalFrame.h"
31 #include "third_party/WebKit/public/web/WebNode.h"
32 #include "third_party/WebKit/public/web/WebNodeList.h"
33 #include "third_party/WebKit/public/web/WebSecurityOrigin.h"
34 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
35 #include "third_party/WebKit/public/web/WebView.h"
36 #include "ui/events/keycodes/keyboard_codes.h"
37 #include "url/gurl.h"
38
39 namespace autofill {
40 namespace {
41
42 // The size above which we stop triggering autocomplete.
43 static const size_t kMaximumTextSizeForAutocomplete = 1000;
44
45 // Maps element names to the actual elements to simplify form filling.
46 typedef std::map<base::string16, blink::WebInputElement> FormInputElementMap;
47
48 // Use the shorter name when referencing SavePasswordProgressLogger::StringID
49 // values to spare line breaks. The code provides enough context for that
50 // already.
51 typedef SavePasswordProgressLogger Logger;
52
53 // Utility struct for form lookup and autofill. When we parse the DOM to look up
54 // a form, in addition to action and origin URL's we have to compare all
55 // necessary form elements. To avoid having to look these up again when we want
56 // to fill the form, the FindFormElements function stores the pointers
57 // in a FormElements* result, referenced to ensure they are safe to use.
58 struct FormElements {
59   blink::WebFormElement form_element;
60   FormInputElementMap input_elements;
61 };
62
63 typedef std::vector<FormElements*> FormElementsList;
64
65 // Helper to search the given form element for the specified input elements
66 // in |data|, and add results to |result|.
67 static bool FindFormInputElements(blink::WebFormElement* fe,
68                                   const FormData& data,
69                                   FormElements* result) {
70   // Loop through the list of elements we need to find on the form in order to
71   // autofill it. If we don't find any one of them, abort processing this
72   // form; it can't be the right one.
73   for (size_t j = 0; j < data.fields.size(); j++) {
74     blink::WebVector<blink::WebNode> temp_elements;
75     fe->getNamedElements(data.fields[j].name, temp_elements);
76
77     // Match the first input element, if any.
78     // |getNamedElements| may return non-input elements where the names match,
79     // so the results are filtered for input elements.
80     // If more than one match is made, then we have ambiguity (due to misuse
81     // of "name" attribute) so is it considered not found.
82     bool found_input = false;
83     for (size_t i = 0; i < temp_elements.size(); ++i) {
84       if (temp_elements[i].to<blink::WebElement>().hasHTMLTagName("input")) {
85         // Check for a non-unique match.
86         if (found_input) {
87           found_input = false;
88           break;
89         }
90
91         // Only fill saved passwords into password fields and usernames into
92         // text fields.
93         blink::WebInputElement input_element =
94             temp_elements[i].to<blink::WebInputElement>();
95         if (input_element.isPasswordField() !=
96             (data.fields[j].form_control_type == "password"))
97           continue;
98
99         // This element matched, add it to our temporary result. It's possible
100         // there are multiple matches, but for purposes of identifying the form
101         // one suffices and if some function needs to deal with multiple
102         // matching elements it can get at them through the FormElement*.
103         // Note: This assignment adds a reference to the InputElement.
104         result->input_elements[data.fields[j].name] = input_element;
105         found_input = true;
106       }
107     }
108
109     // A required element was not found. This is not the right form.
110     // Make sure no input elements from a partially matched form in this
111     // iteration remain in the result set.
112     // Note: clear will remove a reference from each InputElement.
113     if (!found_input) {
114       result->input_elements.clear();
115       return false;
116     }
117   }
118   return true;
119 }
120
121 // Helper to locate form elements identified by |data|.
122 void FindFormElements(blink::WebView* view,
123                       const FormData& data,
124                       FormElementsList* results) {
125   DCHECK(view);
126   DCHECK(results);
127   blink::WebFrame* main_frame = view->mainFrame();
128   if (!main_frame)
129     return;
130
131   GURL::Replacements rep;
132   rep.ClearQuery();
133   rep.ClearRef();
134
135   // Loop through each frame.
136   for (blink::WebFrame* f = main_frame; f; f = f->traverseNext(false)) {
137     blink::WebDocument doc = f->document();
138     if (!doc.isHTMLDocument())
139       continue;
140
141     GURL full_origin(doc.url());
142     if (data.origin != full_origin.ReplaceComponents(rep))
143       continue;
144
145     blink::WebVector<blink::WebFormElement> forms;
146     doc.forms(forms);
147
148     for (size_t i = 0; i < forms.size(); ++i) {
149       blink::WebFormElement fe = forms[i];
150
151       GURL full_action(f->document().completeURL(fe.action()));
152       if (full_action.is_empty()) {
153         // The default action URL is the form's origin.
154         full_action = full_origin;
155       }
156
157       // Action URL must match.
158       if (data.action != full_action.ReplaceComponents(rep))
159         continue;
160
161       scoped_ptr<FormElements> curr_elements(new FormElements);
162       if (!FindFormInputElements(&fe, data, curr_elements.get()))
163         continue;
164
165       // We found the right element.
166       // Note: this assignment adds a reference to |fe|.
167       curr_elements->form_element = fe;
168       results->push_back(curr_elements.release());
169     }
170   }
171 }
172
173 bool IsElementEditable(const blink::WebInputElement& element) {
174   return element.isEnabled() && !element.isReadOnly();
175 }
176
177 bool DoUsernamesMatch(const base::string16& username1,
178                       const base::string16& username2,
179                       bool exact_match) {
180   if (exact_match)
181     return username1 == username2;
182   return StartsWith(username1, username2, true);
183 }
184
185 // Returns |true| if the given element is both editable and has permission to be
186 // autocompleted. The latter can be either because there is no
187 // autocomplete='off' set for the element, or because the flag is set to ignore
188 // autocomplete='off'. Otherwise, returns |false|.
189 bool IsElementAutocompletable(const blink::WebInputElement& element) {
190   return IsElementEditable(element) &&
191          (ShouldIgnoreAutocompleteOffForPasswordFields() ||
192           element.autoComplete());
193 }
194
195 // Returns true if the password specified in |form| is a default value.
196 bool PasswordValueIsDefault(const PasswordForm& form,
197                             blink::WebFormElement form_element) {
198   blink::WebVector<blink::WebNode> temp_elements;
199   form_element.getNamedElements(form.password_element, temp_elements);
200
201   // We are loose in our definition here and will return true if any of the
202   // appropriately named elements match the element to be saved. Currently
203   // we ignore filling passwords where naming is ambigious anyway.
204   for (size_t i = 0; i < temp_elements.size(); ++i) {
205     if (temp_elements[i].to<blink::WebElement>().getAttribute("value") ==
206         form.password_value)
207       return true;
208   }
209   return false;
210 }
211
212 // Log a message including the name, method and action of |form|.
213 void LogHTMLForm(SavePasswordProgressLogger* logger,
214                  SavePasswordProgressLogger::StringID message_id,
215                  const blink::WebFormElement& form) {
216   logger->LogHTMLForm(message_id,
217                       form.name().utf8(),
218                       GURL(form.action().utf8()));
219 }
220
221 }  // namespace
222
223 ////////////////////////////////////////////////////////////////////////////////
224 // PasswordAutofillAgent, public:
225
226 PasswordAutofillAgent::PasswordAutofillAgent(content::RenderView* render_view)
227     : content::RenderViewObserver(render_view),
228       usernames_usage_(NOTHING_TO_AUTOFILL),
229       web_view_(render_view->GetWebView()),
230       logging_state_active_(false),
231       was_username_autofilled_(false),
232       was_password_autofilled_(false),
233       username_selection_start_(0),
234       did_stop_loading_(false),
235       weak_ptr_factory_(this) {
236   Send(new AutofillHostMsg_PasswordAutofillAgentConstructed(routing_id()));
237 }
238
239 PasswordAutofillAgent::~PasswordAutofillAgent() {
240 }
241
242 PasswordAutofillAgent::PasswordValueGatekeeper::PasswordValueGatekeeper()
243     : was_user_gesture_seen_(false) {
244 }
245
246 PasswordAutofillAgent::PasswordValueGatekeeper::~PasswordValueGatekeeper() {
247 }
248
249 void PasswordAutofillAgent::PasswordValueGatekeeper::RegisterElement(
250     blink::WebInputElement* element) {
251   if (was_user_gesture_seen_)
252     ShowValue(element);
253   else
254     elements_.push_back(*element);
255 }
256
257 void PasswordAutofillAgent::PasswordValueGatekeeper::OnUserGesture() {
258   was_user_gesture_seen_ = true;
259
260   for (std::vector<blink::WebInputElement>::iterator it = elements_.begin();
261        it != elements_.end();
262        ++it) {
263     ShowValue(&(*it));
264   }
265
266   elements_.clear();
267 }
268
269 void PasswordAutofillAgent::PasswordValueGatekeeper::Reset() {
270   was_user_gesture_seen_ = false;
271   elements_.clear();
272 }
273
274 void PasswordAutofillAgent::PasswordValueGatekeeper::ShowValue(
275     blink::WebInputElement* element) {
276   if (!element->isNull() && !element->suggestedValue().isNull())
277     element->setValue(element->suggestedValue(), true);
278 }
279
280 bool PasswordAutofillAgent::TextFieldDidEndEditing(
281     const blink::WebInputElement& element) {
282   LoginToPasswordInfoMap::const_iterator iter =
283       login_to_password_info_.find(element);
284   if (iter == login_to_password_info_.end())
285     return false;
286
287   const PasswordFormFillData& fill_data = iter->second.fill_data;
288
289   // If wait_for_username is false, we should have filled when the text changed.
290   if (!fill_data.wait_for_username)
291     return false;
292
293   blink::WebInputElement password = iter->second.password_field;
294   if (!IsElementEditable(password))
295     return false;
296
297   blink::WebInputElement username = element;  // We need a non-const.
298
299   // Do not set selection when ending an editing session, otherwise it can
300   // mess with focus.
301   FillUserNameAndPassword(&username,
302                           &password,
303                           fill_data,
304                           true /* exact_username_match */,
305                           false /* set_selection */);
306   return true;
307 }
308
309 bool PasswordAutofillAgent::TextDidChangeInTextField(
310     const blink::WebInputElement& element) {
311   if (element.isPasswordField()) {
312     // Some login forms have event handlers that put a hash of the password into
313     // a hidden field and then clear the password (http://crbug.com/28910,
314     // http://crbug.com/391693). This method gets called before any of those
315     // handlers run, so save away a copy of the password in case it gets lost.
316     // To honor the user having explicitly cleared the password, even an empty
317     // password will be saved here.
318     ProvisionallySavePassword(
319         element.document().frame(), element.form(), RESTRICTION_NONE);
320     return false;
321   }
322
323   LoginToPasswordInfoMap::const_iterator iter =
324       login_to_password_info_.find(element);
325   if (iter == login_to_password_info_.end())
326     return false;
327
328   // The input text is being changed, so any autofilled password is now
329   // outdated.
330   blink::WebInputElement username = element;  // We need a non-const.
331   username.setAutofilled(false);
332
333   blink::WebInputElement password = iter->second.password_field;
334   if (password.isAutofilled()) {
335     password.setValue(base::string16(), true);
336     password.setAutofilled(false);
337   }
338
339   // If wait_for_username is true we will fill when the username loses focus.
340   if (iter->second.fill_data.wait_for_username)
341     return false;
342
343   if (!element.isText() || !IsElementAutocompletable(element) ||
344       !IsElementAutocompletable(password)) {
345     return false;
346   }
347
348   // Don't inline autocomplete if the user is deleting, that would be confusing.
349   // But refresh the popup.  Note, since this is ours, return true to signal
350   // no further processing is required.
351   if (iter->second.backspace_pressed_last) {
352     ShowSuggestionPopup(iter->second.fill_data, username, false);
353     return true;
354   }
355
356   blink::WebString name = element.nameForAutofill();
357   if (name.isEmpty())
358     return false;  // If the field has no name, then we won't have values.
359
360   // Don't attempt to autofill with values that are too large.
361   if (element.value().length() > kMaximumTextSizeForAutocomplete)
362     return false;
363
364   // The caret position should have already been updated.
365   PerformInlineAutocomplete(element, password, iter->second.fill_data);
366   return true;
367 }
368
369 bool PasswordAutofillAgent::TextFieldHandlingKeyDown(
370     const blink::WebInputElement& element,
371     const blink::WebKeyboardEvent& event) {
372   // If using the new Autofill UI that lives in the browser, it will handle
373   // keypresses before this function. This is not currently an issue but if
374   // the keys handled there or here change, this issue may appear.
375
376   LoginToPasswordInfoMap::iterator iter = login_to_password_info_.find(element);
377   if (iter == login_to_password_info_.end())
378     return false;
379
380   int win_key_code = event.windowsKeyCode;
381   iter->second.backspace_pressed_last =
382       (win_key_code == ui::VKEY_BACK || win_key_code == ui::VKEY_DELETE);
383   return true;
384 }
385
386 bool PasswordAutofillAgent::FillSuggestion(
387     const blink::WebNode& node,
388     const blink::WebString& username,
389     const blink::WebString& password) {
390   blink::WebInputElement username_element;
391   PasswordInfo password_info;
392
393   if (!FindLoginInfo(node, &username_element, &password_info) ||
394       !IsElementAutocompletable(username_element) ||
395       !IsElementAutocompletable(password_info.password_field)) {
396     return false;
397   }
398
399   base::string16 current_username = username_element.value();
400   username_element.setValue(username, true);
401   username_element.setAutofilled(true);
402   username_element.setSelectionRange(username.length(), username.length());
403
404   password_info.password_field.setValue(password, true);
405   password_info.password_field.setAutofilled(true);
406
407   return true;
408 }
409
410 bool PasswordAutofillAgent::PreviewSuggestion(
411     const blink::WebNode& node,
412     const blink::WebString& username,
413     const blink::WebString& password) {
414   blink::WebInputElement username_element;
415   PasswordInfo password_info;
416
417   if (!FindLoginInfo(node, &username_element, &password_info) ||
418       !IsElementAutocompletable(username_element) ||
419       !IsElementAutocompletable(password_info.password_field)) {
420     return false;
421   }
422
423   was_username_autofilled_ = username_element.isAutofilled();
424   username_selection_start_ = username_element.selectionStart();
425   username_element.setSuggestedValue(username);
426   username_element.setAutofilled(true);
427   username_element.setSelectionRange(
428       username_selection_start_,
429       username_element.suggestedValue().length());
430
431   was_password_autofilled_ = password_info.password_field.isAutofilled();
432   password_info.password_field.setSuggestedValue(password);
433   password_info.password_field.setAutofilled(true);
434
435   return true;
436 }
437
438 bool PasswordAutofillAgent::DidClearAutofillSelection(
439     const blink::WebNode& node) {
440   blink::WebInputElement username_element;
441   PasswordInfo password_info;
442   if (!FindLoginInfo(node, &username_element, &password_info))
443     return false;
444
445   ClearPreview(&username_element, &password_info.password_field);
446   return true;
447 }
448
449 bool PasswordAutofillAgent::ShowSuggestions(
450     const blink::WebInputElement& element,
451     bool show_all) {
452   LoginToPasswordInfoMap::const_iterator iter =
453       login_to_password_info_.find(element);
454   if (iter == login_to_password_info_.end())
455     return false;
456
457   // If autocomplete='off' is set on the form elements, no suggestion dialog
458   // should be shown. However, return |true| to indicate that this is a known
459   // password form and that the request to show suggestions has been handled (as
460   // a no-op).
461   if (!IsElementAutocompletable(element) ||
462       !IsElementAutocompletable(iter->second.password_field))
463     return true;
464
465   return ShowSuggestionPopup(iter->second.fill_data, element, show_all);
466 }
467
468 bool PasswordAutofillAgent::OriginCanAccessPasswordManager(
469     const blink::WebSecurityOrigin& origin) {
470   return origin.canAccessPasswordManager();
471 }
472
473 void PasswordAutofillAgent::OnDynamicFormsSeen(blink::WebFrame* frame) {
474   SendPasswordForms(frame, false /* only_visible */);
475 }
476
477 void PasswordAutofillAgent::FirstUserGestureObserved() {
478   gatekeeper_.OnUserGesture();
479 }
480
481 void PasswordAutofillAgent::SendPasswordForms(blink::WebFrame* frame,
482                                               bool only_visible) {
483   scoped_ptr<RendererSavePasswordProgressLogger> logger;
484   if (logging_state_active_) {
485     logger.reset(new RendererSavePasswordProgressLogger(this, routing_id()));
486     logger->LogMessage(Logger::STRING_SEND_PASSWORD_FORMS_METHOD);
487     logger->LogBoolean(Logger::STRING_ONLY_VISIBLE, only_visible);
488   }
489
490   // Make sure that this security origin is allowed to use password manager.
491   blink::WebSecurityOrigin origin = frame->document().securityOrigin();
492   if (logger) {
493     logger->LogURL(Logger::STRING_SECURITY_ORIGIN,
494                    GURL(origin.toString().utf8()));
495   }
496   if (!OriginCanAccessPasswordManager(origin)) {
497     if (logger) {
498       logger->LogMessage(Logger::STRING_SECURITY_ORIGIN_FAILURE);
499       logger->LogMessage(Logger::STRING_DECISION_DROP);
500     }
501     return;
502   }
503
504   // Checks whether the webpage is a redirect page or an empty page.
505   if (IsWebpageEmpty(frame)) {
506     if (logger) {
507       logger->LogMessage(Logger::STRING_WEBPAGE_EMPTY);
508       logger->LogMessage(Logger::STRING_DECISION_DROP);
509     }
510     return;
511   }
512
513   blink::WebVector<blink::WebFormElement> forms;
514   frame->document().forms(forms);
515   if (logger)
516     logger->LogNumber(Logger::STRING_NUMBER_OF_ALL_FORMS, forms.size());
517
518   std::vector<PasswordForm> password_forms;
519   for (size_t i = 0; i < forms.size(); ++i) {
520     const blink::WebFormElement& form = forms[i];
521     bool is_form_visible = IsWebNodeVisible(form);
522     if (logger) {
523       LogHTMLForm(logger.get(), Logger::STRING_FORM_FOUND_ON_PAGE, form);
524       logger->LogBoolean(Logger::STRING_FORM_IS_VISIBLE, is_form_visible);
525     }
526
527     // If requested, ignore non-rendered forms, e.g. those styled with
528     // display:none.
529     if (only_visible && !is_form_visible)
530       continue;
531
532     scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form));
533     if (password_form.get()) {
534       if (logger) {
535         logger->LogPasswordForm(Logger::STRING_FORM_IS_PASSWORD,
536                                 *password_form);
537       }
538       password_forms.push_back(*password_form);
539     }
540   }
541
542   if (password_forms.empty() && !only_visible) {
543     // We need to send the PasswordFormsRendered message regardless of whether
544     // there are any forms visible, as this is also the code path that triggers
545     // showing the infobar.
546     return;
547   }
548
549   if (only_visible) {
550     Send(new AutofillHostMsg_PasswordFormsRendered(routing_id(),
551                                                    password_forms,
552                                                    did_stop_loading_));
553   } else {
554     Send(new AutofillHostMsg_PasswordFormsParsed(routing_id(), password_forms));
555   }
556 }
557
558 bool PasswordAutofillAgent::OnMessageReceived(const IPC::Message& message) {
559   bool handled = true;
560   IPC_BEGIN_MESSAGE_MAP(PasswordAutofillAgent, message)
561     IPC_MESSAGE_HANDLER(AutofillMsg_FillPasswordForm, OnFillPasswordForm)
562     IPC_MESSAGE_HANDLER(AutofillMsg_SetLoggingState, OnSetLoggingState)
563     IPC_MESSAGE_UNHANDLED(handled = false)
564   IPC_END_MESSAGE_MAP()
565   return handled;
566 }
567
568 void PasswordAutofillAgent::DidStartLoading() {
569   did_stop_loading_ = false;
570   if (usernames_usage_ != NOTHING_TO_AUTOFILL) {
571     UMA_HISTOGRAM_ENUMERATION("PasswordManager.OtherPossibleUsernamesUsage",
572                               usernames_usage_,
573                               OTHER_POSSIBLE_USERNAMES_MAX);
574     usernames_usage_ = NOTHING_TO_AUTOFILL;
575   }
576 }
577
578 void PasswordAutofillAgent::DidFinishDocumentLoad(blink::WebLocalFrame* frame) {
579   // The |frame| contents have been parsed, but not yet rendered.  Let the
580   // PasswordManager know that forms are loaded, even though we can't yet tell
581   // whether they're visible.
582   SendPasswordForms(frame, false);
583 }
584
585 void PasswordAutofillAgent::DidFinishLoad(blink::WebLocalFrame* frame) {
586   // The |frame| contents have been rendered.  Let the PasswordManager know
587   // which of the loaded frames are actually visible to the user.  This also
588   // triggers the "Save password?" infobar if the user just submitted a password
589   // form.
590   SendPasswordForms(frame, true);
591 }
592
593 void PasswordAutofillAgent::DidStopLoading() {
594   did_stop_loading_ = true;
595 }
596
597 void PasswordAutofillAgent::FrameDetached(blink::WebFrame* frame) {
598   FrameClosing(frame);
599 }
600
601 void PasswordAutofillAgent::FrameWillClose(blink::WebFrame* frame) {
602   FrameClosing(frame);
603 }
604
605 void PasswordAutofillAgent::WillSendSubmitEvent(
606     blink::WebLocalFrame* frame,
607     const blink::WebFormElement& form) {
608   // Forms submitted via XHR are not seen by WillSubmitForm if the default
609   // onsubmit handler is overridden. Such submission first gets detected in
610   // DidStartProvisionalLoad, which no longer knows about the particular form,
611   // and uses the candidate stored in |provisionally_saved_forms_|.
612   //
613   // User-typed password will get stored to |provisionally_saved_forms_| in
614   // TextDidChangeInTextField. Autofilled or JavaScript-copied passwords need to
615   // be saved here.
616   //
617   // Only non-empty passwords are saved here. Empty passwords were likely
618   // cleared by some scripts (http://crbug.com/28910, http://crbug.com/391693).
619   // Had the user cleared the password, |provisionally_saved_forms_| would
620   // already have been updated in TextDidChangeInTextField.
621   ProvisionallySavePassword(frame, form, RESTRICTION_NON_EMPTY_PASSWORD);
622 }
623
624 void PasswordAutofillAgent::WillSubmitForm(blink::WebLocalFrame* frame,
625                                            const blink::WebFormElement& form) {
626   scoped_ptr<RendererSavePasswordProgressLogger> logger;
627   if (logging_state_active_) {
628     logger.reset(new RendererSavePasswordProgressLogger(this, routing_id()));
629     logger->LogMessage(Logger::STRING_WILL_SUBMIT_FORM_METHOD);
630     LogHTMLForm(logger.get(), Logger::STRING_HTML_FORM_FOR_SUBMIT, form);
631   }
632
633   scoped_ptr<PasswordForm> submitted_form = CreatePasswordForm(form);
634
635   // If there is a provisionally saved password, copy over the previous
636   // password value so we get the user's typed password, not the value that
637   // may have been transformed for submit.
638   // TODO(gcasto): Do we need to have this action equality check? Is it trying
639   // to prevent accidentally copying over passwords from a different form?
640   if (submitted_form) {
641     if (logger) {
642       logger->LogPasswordForm(Logger::STRING_CREATED_PASSWORD_FORM,
643                               *submitted_form);
644     }
645     if (provisionally_saved_forms_[frame].get() &&
646         submitted_form->action == provisionally_saved_forms_[frame]->action) {
647       if (logger)
648         logger->LogMessage(Logger::STRING_SUBMITTED_PASSWORD_REPLACED);
649       submitted_form->password_value =
650           provisionally_saved_forms_[frame]->password_value;
651       submitted_form->new_password_value =
652           provisionally_saved_forms_[frame]->new_password_value;
653     }
654
655     // Some observers depend on sending this information now instead of when
656     // the frame starts loading. If there are redirects that cause a new
657     // RenderView to be instantiated (such as redirects to the WebStore)
658     // we will never get to finish the load.
659     Send(new AutofillHostMsg_PasswordFormSubmitted(routing_id(),
660                                                    *submitted_form));
661     // Remove reference since we have already submitted this form.
662     provisionally_saved_forms_.erase(frame);
663   } else if (logger) {
664     logger->LogMessage(Logger::STRING_DECISION_DROP);
665   }
666 }
667
668 blink::WebFrame* PasswordAutofillAgent::CurrentOrChildFrameWithSavedForms(
669     const blink::WebFrame* current_frame) {
670   for (FrameToPasswordFormMap::const_iterator it =
671            provisionally_saved_forms_.begin();
672        it != provisionally_saved_forms_.end();
673        ++it) {
674     blink::WebFrame* form_frame = it->first;
675     // The check that the returned frame is related to |current_frame| is mainly
676     // for double-checking. There should not be any unrelated frames in
677     // |provisionally_saved_forms_|, because the map is cleared after
678     // navigation. If there are reasons to remove this check in the future and
679     // keep just the first frame found, it might be a good idea to add a UMA
680     // statistic or a similar check on how many frames are here to choose from.
681     if (current_frame == form_frame ||
682         current_frame->findChildByName(form_frame->assignedName())) {
683       return form_frame;
684     }
685   }
686   return NULL;
687 }
688
689 void PasswordAutofillAgent::DidStartProvisionalLoad(
690     blink::WebLocalFrame* frame) {
691   scoped_ptr<RendererSavePasswordProgressLogger> logger;
692   if (logging_state_active_) {
693     logger.reset(new RendererSavePasswordProgressLogger(this, routing_id()));
694     logger->LogMessage(Logger::STRING_DID_START_PROVISIONAL_LOAD_METHOD);
695   }
696
697   if (!frame->parent()) {
698     // If the navigation is not triggered by a user gesture, e.g. by some ajax
699     // callback, then inherit the submitted password form from the previous
700     // state. This fixes the no password save issue for ajax login, tracked in
701     // [http://crbug/43219]. Note that this still fails for sites that use
702     // synchonous XHR as isProcessingUserGesture() will return true.
703     blink::WebFrame* form_frame = CurrentOrChildFrameWithSavedForms(frame);
704     if (logger) {
705       logger->LogBoolean(Logger::STRING_FORM_FRAME_EQ_FRAME,
706                          form_frame == frame);
707     }
708     // Bug fix for crbug.com/368690. isProcessingUserGesture() is false when
709     // the user is performing actions outside the page (e.g. typed url,
710     // history navigation). We don't want to trigger saving in these cases.
711     content::DocumentState* document_state =
712         content::DocumentState::FromDataSource(
713             frame->provisionalDataSource());
714     content::NavigationState* navigation_state =
715         document_state->navigation_state();
716     if (content::PageTransitionIsWebTriggerable(
717             navigation_state->transition_type()) &&
718         !blink::WebUserGestureIndicator::isProcessingUserGesture()) {
719       // If onsubmit has been called, try and save that form.
720       if (provisionally_saved_forms_[form_frame].get()) {
721         if (logger) {
722           logger->LogPasswordForm(
723               Logger::STRING_PROVISIONALLY_SAVED_FORM_FOR_FRAME,
724               *provisionally_saved_forms_[form_frame]);
725         }
726         Send(new AutofillHostMsg_PasswordFormSubmitted(
727             routing_id(), *provisionally_saved_forms_[form_frame]));
728         provisionally_saved_forms_.erase(form_frame);
729       } else {
730         // Loop through the forms on the page looking for one that has been
731         // filled out. If one exists, try and save the credentials.
732         blink::WebVector<blink::WebFormElement> forms;
733         frame->document().forms(forms);
734
735         bool password_forms_found = false;
736         for (size_t i = 0; i < forms.size(); ++i) {
737           blink::WebFormElement form_element = forms[i];
738           if (logger) {
739             LogHTMLForm(
740                 logger.get(), Logger::STRING_FORM_FOUND_ON_PAGE, form_element);
741           }
742           scoped_ptr<PasswordForm> password_form(
743               CreatePasswordForm(form_element));
744           if (password_form.get() && !password_form->username_value.empty() &&
745               !password_form->password_value.empty() &&
746               !PasswordValueIsDefault(*password_form, form_element)) {
747             password_forms_found = true;
748             if (logger) {
749               logger->LogPasswordForm(
750                   Logger::STRING_PASSWORD_FORM_FOUND_ON_PAGE, *password_form);
751             }
752             Send(new AutofillHostMsg_PasswordFormSubmitted(routing_id(),
753                                                            *password_form));
754           }
755         }
756         if (!password_forms_found && logger) {
757           logger->LogMessage(Logger::STRING_DECISION_DROP);
758         }
759       }
760     }
761     // Clear the whole map during main frame navigation.
762     provisionally_saved_forms_.clear();
763
764     // This is a new navigation, so require a new user gesture before filling in
765     // passwords.
766     gatekeeper_.Reset();
767   } else {
768     if (logger)
769       logger->LogMessage(Logger::STRING_DECISION_DROP);
770   }
771 }
772
773 void PasswordAutofillAgent::OnFillPasswordForm(
774     const PasswordFormFillData& form_data) {
775   if (usernames_usage_ == NOTHING_TO_AUTOFILL) {
776     if (form_data.other_possible_usernames.size())
777       usernames_usage_ = OTHER_POSSIBLE_USERNAMES_PRESENT;
778     else if (usernames_usage_ == NOTHING_TO_AUTOFILL)
779       usernames_usage_ = OTHER_POSSIBLE_USERNAMES_ABSENT;
780   }
781
782   FormElementsList forms;
783   // We own the FormElements* in forms.
784   FindFormElements(render_view()->GetWebView(), form_data.basic_data, &forms);
785   FormElementsList::iterator iter;
786   for (iter = forms.begin(); iter != forms.end(); ++iter) {
787     scoped_ptr<FormElements> form_elements(*iter);
788
789     // Attach autocomplete listener to enable selecting alternate logins.
790     // First, get pointers to username element.
791     blink::WebInputElement username_element =
792         form_elements->input_elements[form_data.basic_data.fields[0].name];
793
794     // Get pointer to password element. (We currently only support single
795     // password forms).
796     blink::WebInputElement password_element =
797         form_elements->input_elements[form_data.basic_data.fields[1].name];
798
799     // If wait_for_username is true, we don't want to initially fill the form
800     // until the user types in a valid username.
801     if (!form_data.wait_for_username)
802       FillFormOnPasswordRecieved(form_data, username_element, password_element);
803
804     // We might have already filled this form if there are two <form> elements
805     // with identical markup.
806     if (login_to_password_info_.find(username_element) !=
807         login_to_password_info_.end())
808       continue;
809
810     PasswordInfo password_info;
811     password_info.fill_data = form_data;
812     password_info.password_field = password_element;
813     login_to_password_info_[username_element] = password_info;
814
815     FormData form;
816     FormFieldData field;
817     FindFormAndFieldForFormControlElement(
818         username_element, &form, &field, REQUIRE_NONE);
819     Send(new AutofillHostMsg_AddPasswordFormMapping(
820         routing_id(), field, form_data));
821   }
822 }
823
824 void PasswordAutofillAgent::OnSetLoggingState(bool active) {
825   logging_state_active_ = active;
826 }
827
828 ////////////////////////////////////////////////////////////////////////////////
829 // PasswordAutofillAgent, private:
830
831 void PasswordAutofillAgent::GetSuggestions(
832     const PasswordFormFillData& fill_data,
833     const base::string16& input,
834     std::vector<base::string16>* suggestions,
835     std::vector<base::string16>* realms,
836     bool show_all) {
837   if (show_all ||
838       StartsWith(fill_data.basic_data.fields[0].value, input, false)) {
839     suggestions->push_back(fill_data.basic_data.fields[0].value);
840     realms->push_back(base::UTF8ToUTF16(fill_data.preferred_realm));
841   }
842
843   for (PasswordFormFillData::LoginCollection::const_iterator iter =
844            fill_data.additional_logins.begin();
845        iter != fill_data.additional_logins.end();
846        ++iter) {
847     if (show_all || StartsWith(iter->first, input, false)) {
848       suggestions->push_back(iter->first);
849       realms->push_back(base::UTF8ToUTF16(iter->second.realm));
850     }
851   }
852
853   for (PasswordFormFillData::UsernamesCollection::const_iterator iter =
854            fill_data.other_possible_usernames.begin();
855        iter != fill_data.other_possible_usernames.end();
856        ++iter) {
857     for (size_t i = 0; i < iter->second.size(); ++i) {
858       if (show_all || StartsWith(iter->second[i], input, false)) {
859         usernames_usage_ = OTHER_POSSIBLE_USERNAME_SHOWN;
860         suggestions->push_back(iter->second[i]);
861         realms->push_back(base::UTF8ToUTF16(iter->first.realm));
862       }
863     }
864   }
865 }
866
867 bool PasswordAutofillAgent::ShowSuggestionPopup(
868     const PasswordFormFillData& fill_data,
869     const blink::WebInputElement& user_input,
870     bool show_all) {
871   blink::WebFrame* frame = user_input.document().frame();
872   if (!frame)
873     return false;
874
875   blink::WebView* webview = frame->view();
876   if (!webview)
877     return false;
878
879   std::vector<base::string16> suggestions;
880   std::vector<base::string16> realms;
881   GetSuggestions(
882       fill_data, user_input.value(), &suggestions, &realms, show_all);
883   DCHECK_EQ(suggestions.size(), realms.size());
884
885   FormData form;
886   FormFieldData field;
887   FindFormAndFieldForFormControlElement(
888       user_input, &form, &field, REQUIRE_NONE);
889
890   blink::WebInputElement selected_element = user_input;
891   gfx::Rect bounding_box(selected_element.boundsInViewportSpace());
892
893   float scale = web_view_->pageScaleFactor();
894   gfx::RectF bounding_box_scaled(bounding_box.x() * scale,
895                                  bounding_box.y() * scale,
896                                  bounding_box.width() * scale,
897                                  bounding_box.height() * scale);
898   Send(new AutofillHostMsg_ShowPasswordSuggestions(
899       routing_id(), field, bounding_box_scaled, suggestions, realms));
900   return !suggestions.empty();
901 }
902
903 void PasswordAutofillAgent::FillFormOnPasswordRecieved(
904     const PasswordFormFillData& fill_data,
905     blink::WebInputElement username_element,
906     blink::WebInputElement password_element) {
907   // Do not fill if the password field is in an iframe.
908   DCHECK(password_element.document().frame());
909   if (password_element.document().frame()->parent())
910     return;
911
912   if (!ShouldIgnoreAutocompleteOffForPasswordFields() &&
913       !username_element.form().autoComplete())
914     return;
915
916   // If we can't modify the password, don't try to set the username
917   if (!IsElementAutocompletable(password_element))
918     return;
919
920   // Try to set the username to the preferred name, but only if the field
921   // can be set and isn't prefilled.
922   if (IsElementAutocompletable(username_element) &&
923       username_element.value().isEmpty()) {
924     // TODO(tkent): Check maxlength and pattern.
925     username_element.setValue(fill_data.basic_data.fields[0].value, true);
926   }
927
928   // Fill if we have an exact match for the username. Note that this sets
929   // username to autofilled.
930   FillUserNameAndPassword(&username_element,
931                           &password_element,
932                           fill_data,
933                           true /* exact_username_match */,
934                           false /* set_selection */);
935 }
936
937 bool PasswordAutofillAgent::FillUserNameAndPassword(
938     blink::WebInputElement* username_element,
939     blink::WebInputElement* password_element,
940     const PasswordFormFillData& fill_data,
941     bool exact_username_match,
942     bool set_selection) {
943   base::string16 current_username = username_element->value();
944   // username and password will contain the match found if any.
945   base::string16 username;
946   base::string16 password;
947
948   // Look for any suitable matches to current field text.
949   if (DoUsernamesMatch(fill_data.basic_data.fields[0].value,
950                        current_username,
951                        exact_username_match)) {
952     username = fill_data.basic_data.fields[0].value;
953     password = fill_data.basic_data.fields[1].value;
954   } else {
955     // Scan additional logins for a match.
956     PasswordFormFillData::LoginCollection::const_iterator iter;
957     for (iter = fill_data.additional_logins.begin();
958          iter != fill_data.additional_logins.end();
959          ++iter) {
960       if (DoUsernamesMatch(
961               iter->first, current_username, exact_username_match)) {
962         username = iter->first;
963         password = iter->second.password;
964         break;
965       }
966     }
967
968     // Check possible usernames.
969     if (username.empty() && password.empty()) {
970       for (PasswordFormFillData::UsernamesCollection::const_iterator iter =
971                fill_data.other_possible_usernames.begin();
972            iter != fill_data.other_possible_usernames.end();
973            ++iter) {
974         for (size_t i = 0; i < iter->second.size(); ++i) {
975           if (DoUsernamesMatch(
976                   iter->second[i], current_username, exact_username_match)) {
977             usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED;
978             username = iter->second[i];
979             password = iter->first.password;
980             break;
981           }
982         }
983         if (!username.empty() && !password.empty())
984           break;
985       }
986     }
987   }
988   if (password.empty())
989     return false;  // No match was found.
990
991   // TODO(tkent): Check maxlength and pattern for both username and password
992   // fields.
993
994   // Don't fill username if password can't be set.
995   if (!IsElementAutocompletable(*password_element)) {
996     return false;
997   }
998
999   // Input matches the username, fill in required values.
1000   if (IsElementAutocompletable(*username_element)) {
1001     username_element->setValue(username, true);
1002     username_element->setAutofilled(true);
1003
1004     if (set_selection) {
1005       username_element->setSelectionRange(current_username.length(),
1006                                           username.length());
1007     }
1008   } else if (current_username != username) {
1009     // If the username can't be filled and it doesn't match a saved password
1010     // as is, don't autofill a password.
1011     return false;
1012   }
1013
1014   // Wait to fill in the password until a user gesture occurs. This is to make
1015   // sure that we do not fill in the DOM with a password until we believe the
1016   // user is intentionally interacting with the page.
1017   password_element->setSuggestedValue(password);
1018   gatekeeper_.RegisterElement(password_element);
1019
1020   password_element->setAutofilled(true);
1021   return true;
1022 }
1023
1024 void PasswordAutofillAgent::PerformInlineAutocomplete(
1025     const blink::WebInputElement& username_input,
1026     const blink::WebInputElement& password_input,
1027     const PasswordFormFillData& fill_data) {
1028   DCHECK(!fill_data.wait_for_username);
1029
1030   // We need non-const versions of the username and password inputs.
1031   blink::WebInputElement username = username_input;
1032   blink::WebInputElement password = password_input;
1033
1034   // Don't inline autocomplete if the caret is not at the end.
1035   // TODO(jcivelli): is there a better way to test the caret location?
1036   if (username.selectionStart() != username.selectionEnd() ||
1037       username.selectionEnd() != static_cast<int>(username.value().length())) {
1038     return;
1039   }
1040
1041   // Show the popup with the list of available usernames.
1042   ShowSuggestionPopup(fill_data, username, false);
1043
1044 #if !defined(OS_ANDROID)
1045   // Fill the user and password field with the most relevant match. Android
1046   // only fills in the fields after the user clicks on the suggestion popup.
1047   FillUserNameAndPassword(&username,
1048                           &password,
1049                           fill_data,
1050                           false /* exact_username_match */,
1051                           true /* set_selection */);
1052 #endif
1053 }
1054
1055 void PasswordAutofillAgent::FrameClosing(const blink::WebFrame* frame) {
1056   for (LoginToPasswordInfoMap::iterator iter = login_to_password_info_.begin();
1057        iter != login_to_password_info_.end();) {
1058     if (iter->first.document().frame() == frame)
1059       login_to_password_info_.erase(iter++);
1060     else
1061       ++iter;
1062   }
1063   for (FrameToPasswordFormMap::iterator iter =
1064            provisionally_saved_forms_.begin();
1065        iter != provisionally_saved_forms_.end();) {
1066     if (iter->first == frame)
1067       provisionally_saved_forms_.erase(iter++);
1068     else
1069       ++iter;
1070   }
1071 }
1072
1073 bool PasswordAutofillAgent::FindLoginInfo(const blink::WebNode& node,
1074                                           blink::WebInputElement* found_input,
1075                                           PasswordInfo* found_password) {
1076   if (!node.isElementNode())
1077     return false;
1078
1079   blink::WebElement element = node.toConst<blink::WebElement>();
1080   if (!element.hasHTMLTagName("input"))
1081     return false;
1082
1083   blink::WebInputElement input = element.to<blink::WebInputElement>();
1084   LoginToPasswordInfoMap::iterator iter = login_to_password_info_.find(input);
1085   if (iter == login_to_password_info_.end())
1086     return false;
1087
1088   *found_input = input;
1089   *found_password = iter->second;
1090   return true;
1091 }
1092
1093 void PasswordAutofillAgent::ClearPreview(
1094     blink::WebInputElement* username,
1095     blink::WebInputElement* password) {
1096   if (!username->suggestedValue().isEmpty()) {
1097     username->setSuggestedValue(blink::WebString());
1098     username->setAutofilled(was_username_autofilled_);
1099     username->setSelectionRange(username_selection_start_,
1100                                 username->value().length());
1101   }
1102   if (!password->suggestedValue().isEmpty()) {
1103       password->setSuggestedValue(blink::WebString());
1104       password->setAutofilled(was_password_autofilled_);
1105   }
1106 }
1107
1108 void PasswordAutofillAgent::ProvisionallySavePassword(
1109     blink::WebLocalFrame* frame,
1110     const blink::WebFormElement& form,
1111     ProvisionallySaveRestriction restriction) {
1112   DCHECK(frame);
1113   scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form));
1114   if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD &&
1115                          password_form->password_value.empty() &&
1116                          password_form->new_password_value.empty())) {
1117     return;
1118   }
1119   provisionally_saved_forms_[frame].reset(password_form.release());
1120 }
1121
1122 }  // namespace autofill