Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / components / autofill / content / renderer / password_generation_agent.cc
index c81c154..147b773 100644 (file)
 #include "components/autofill/core/common/password_generation_util.h"
 #include "content/public/renderer/render_view.h"
 #include "google_apis/gaia/gaia_urls.h"
-#include "third_party/WebKit/public/platform/WebCString.h"
-#include "third_party/WebKit/public/platform/WebRect.h"
 #include "third_party/WebKit/public/platform/WebVector.h"
 #include "third_party/WebKit/public/web/WebDocument.h"
 #include "third_party/WebKit/public/web/WebFormElement.h"
-#include "third_party/WebKit/public/web/WebFrame.h"
 #include "third_party/WebKit/public/web/WebInputElement.h"
+#include "third_party/WebKit/public/web/WebLocalFrame.h"
 #include "third_party/WebKit/public/web/WebSecurityOrigin.h"
 #include "third_party/WebKit/public/web/WebView.h"
 #include "ui/gfx/rect.h"
@@ -94,6 +92,15 @@ bool ContainsForm(const std::vector<autofill::FormData>& forms,
   return false;
 }
 
+void CopyValueToAllInputElements(
+    const blink::WebString value,
+    std::vector<blink::WebInputElement>* elements) {
+  for (std::vector<blink::WebInputElement>::iterator it = elements->begin();
+       it != elements->end(); ++it) {
+    it->setValue(value, true /* sendEvents */);
+  }
+}
+
 }  // namespace
 
 PasswordGenerationAgent::PasswordGenerationAgent(
@@ -102,12 +109,15 @@ PasswordGenerationAgent::PasswordGenerationAgent(
       render_view_(render_view),
       password_is_generated_(false),
       password_edited_(false),
+      generation_popup_shown_(false),
+      editing_popup_shown_(false),
       enabled_(password_generation::IsPasswordGenerationEnabled()) {
   DVLOG(2) << "Password Generation is " << (enabled_ ? "Enabled" : "Disabled");
 }
 PasswordGenerationAgent::~PasswordGenerationAgent() {}
 
-void PasswordGenerationAgent::DidFinishDocumentLoad(blink::WebFrame* frame) {
+void PasswordGenerationAgent::DidFinishDocumentLoad(
+    blink::WebLocalFrame* frame) {
   // In every navigation, the IPC message sent by the password autofill manager
   // to query whether the current form is blacklisted or not happens when the
   // document load finishes, so we need to clear previous states here before we
@@ -120,6 +130,15 @@ void PasswordGenerationAgent::DidFinishDocumentLoad(blink::WebFrame* frame) {
     generation_enabled_forms_.clear();
     generation_element_.reset();
     possible_account_creation_form_.reset(new PasswordForm());
+
+    // Log statistics after navigation so that we only log once per page.
+    if (password_elements_.empty()) {
+      password_generation::LogPasswordGenerationEvent(
+          password_generation::NO_SIGN_UP_DETECTED);
+    } else {
+      password_generation::LogPasswordGenerationEvent(
+          password_generation::SIGN_UP_DETECTED);
+    }
     password_elements_.clear();
     password_is_generated_ = false;
     if (password_edited_) {
@@ -127,10 +146,31 @@ void PasswordGenerationAgent::DidFinishDocumentLoad(blink::WebFrame* frame) {
           password_generation::PASSWORD_EDITED);
     }
     password_edited_ = false;
+
+    if (generation_popup_shown_) {
+      password_generation::LogPasswordGenerationEvent(
+          password_generation::GENERATION_POPUP_SHOWN);
+    }
+    generation_popup_shown_ = false;
+
+    if (editing_popup_shown_) {
+      password_generation::LogPasswordGenerationEvent(
+          password_generation::EDITING_POPUP_SHOWN);
+    }
+    editing_popup_shown_ = false;
   }
 }
 
-void PasswordGenerationAgent::DidFinishLoad(blink::WebFrame* frame) {
+void PasswordGenerationAgent::OnDynamicFormsSeen(blink::WebLocalFrame* frame) {
+  FindPossibleGenerationForm(frame);
+}
+
+void PasswordGenerationAgent::DidFinishLoad(blink::WebLocalFrame* frame) {
+  FindPossibleGenerationForm(frame);
+}
+
+void PasswordGenerationAgent::FindPossibleGenerationForm(
+    blink::WebLocalFrame* frame) {
   if (!enabled_)
     return;
 
@@ -139,6 +179,10 @@ void PasswordGenerationAgent::DidFinishLoad(blink::WebFrame* frame) {
   if (!ShouldAnalyzeDocument(frame->document()))
     return;
 
+  // If we have already found a signup form for this page, no need to continue.
+  if (!password_elements_.empty())
+    return;
+
   blink::WebVector<blink::WebFormElement> forms;
   frame->document().forms(forms);
   for (size_t i = 0; i < forms.size(); ++i) {
@@ -163,8 +207,6 @@ void PasswordGenerationAgent::DidFinishLoad(blink::WebFrame* frame) {
     std::vector<blink::WebInputElement> passwords;
     if (GetAccountCreationPasswordFields(forms[i], &passwords)) {
       DVLOG(2) << "Account creation form detected";
-      password_generation::LogPasswordGenerationEvent(
-          password_generation::SIGN_UP_DETECTED);
       password_elements_ = passwords;
       possible_account_creation_form_.swap(password_form);
       DetermineGenerationElement();
@@ -172,8 +214,6 @@ void PasswordGenerationAgent::DidFinishLoad(blink::WebFrame* frame) {
       return;
     }
   }
-  password_generation::LogPasswordGenerationEvent(
-      password_generation::NO_SIGN_UP_DETECTED);
 }
 
 bool PasswordGenerationAgent::ShouldAnalyzeDocument(
@@ -216,7 +256,7 @@ void PasswordGenerationAgent::OnPasswordAccepted(
   for (std::vector<blink::WebInputElement>::iterator it =
            password_elements_.begin();
        it != password_elements_.end(); ++it) {
-    it->setValue(password);
+    it->setValue(password, true /* sendEvents */);
     it->setAutofilled(true);
     // Advance focus to the next input field. We assume password fields in
     // an account creation form are always adjacent.
@@ -265,32 +305,39 @@ void PasswordGenerationAgent::DetermineGenerationElement() {
       password_generation::GENERATION_AVAILABLE);
 }
 
-void PasswordGenerationAgent::FocusedNodeChanged(const blink::WebNode& node) {
+bool PasswordGenerationAgent::FocusedNodeHasChanged(
+    const blink::WebNode& node) {
   if (!generation_element_.isNull())
     generation_element_.setShouldRevealPassword(false);
 
   if (node.isNull() || !node.isElementNode())
-    return;
+    return false;
 
   const blink::WebElement web_element = node.toConst<blink::WebElement>();
   if (!web_element.document().frame())
-    return;
+    return false;
 
   const blink::WebInputElement* element = toWebInputElement(&web_element);
   if (!element || *element != generation_element_)
-    return;
+    return false;
 
   if (password_is_generated_) {
     generation_element_.setShouldRevealPassword(true);
     ShowEditingPopup();
+    return true;
   }
 
-  // Only trigger if the password field is empty.
+  // Assume that if the password field has less than kMaximumOfferSize
+  // characters then the user is not finished typing their password and display
+  // the password suggestion.
   if (!element->isReadOnly() &&
       element->isEnabled() &&
-      element->value().isEmpty()) {
+      element->value().length() <= kMaximumOfferSize) {
     ShowGenerationPopup();
+    return true;
   }
+
+  return false;
 }
 
 bool PasswordGenerationAgent::TextDidChangeInTextField(
@@ -303,6 +350,7 @@ bool PasswordGenerationAgent::TextDidChangeInTextField(
       // User generated a password and then deleted it.
       password_generation::LogPasswordGenerationEvent(
           password_generation::PASSWORD_DELETED);
+      CopyValueToAllInputElements(element.value(), &password_elements_);
     }
 
     // Do not treat the password as generated.
@@ -312,17 +360,18 @@ bool PasswordGenerationAgent::TextDidChangeInTextField(
 
     // Offer generation again.
     ShowGenerationPopup();
-  } else if (!password_is_generated_) {
+  } else if (password_is_generated_) {
+    password_edited_ = true;
+    // Mirror edits to any confirmation password fields.
+    CopyValueToAllInputElements(element.value(), &password_elements_);
+  } else if (element.value().length() > kMaximumOfferSize) {
     // User has rejected the feature and has started typing a password.
     HidePopup();
   } else {
-    password_edited_ = true;
-    // Mirror edits to any confirmation password fields.
-    for (std::vector<blink::WebInputElement>::iterator it =
-             password_elements_.begin();
-         it != password_elements_.end(); ++it) {
-      it->setValue(element.value());
-    }
+    // Password isn't generated and there are fewer than kMaximumOfferSize
+    // characters typed, so keep offering the password. Note this function
+    // will just keep the previous popup if one is already showing.
+    ShowGenerationPopup();
   }
 
   return true;
@@ -339,8 +388,7 @@ void PasswordGenerationAgent::ShowGenerationPopup() {
       generation_element_.maxLength(),
       *possible_account_creation_form_));
 
-  password_generation::LogPasswordGenerationEvent(
-      password_generation::GENERATION_POPUP_SHOWN);
+  generation_popup_shown_ = true;
 }
 
 void PasswordGenerationAgent::ShowEditingPopup() {
@@ -353,8 +401,7 @@ void PasswordGenerationAgent::ShowEditingPopup() {
       bounding_box_scaled,
       *possible_account_creation_form_));
 
-  password_generation::LogPasswordGenerationEvent(
-      password_generation::EDITING_POPUP_SHOWN);
+  editing_popup_shown_ = true;
 }
 
 void PasswordGenerationAgent::HidePopup() {