| 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 #include "components/autofill/content/renderer/password_generation_agent.h" | 5 #include "components/autofill/content/renderer/password_generation_agent.h" |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
| 10 #include "components/autofill/content/common/autofill_messages.h" | 10 #include "components/autofill/content/common/autofill_messages.h" |
| 11 #include "components/autofill/content/renderer/form_autofill_util.h" | 11 #include "components/autofill/content/renderer/form_autofill_util.h" |
| 12 #include "components/autofill/content/renderer/password_form_conversion_utils.h" | 12 #include "components/autofill/content/renderer/password_form_conversion_utils.h" |
| 13 #include "components/autofill/core/common/autofill_switches.h" | 13 #include "components/autofill/core/common/autofill_switches.h" |
| 14 #include "components/autofill/core/common/form_data.h" | 14 #include "components/autofill/core/common/form_data.h" |
| 15 #include "components/autofill/core/common/password_form.h" | 15 #include "components/autofill/core/common/password_form.h" |
| 16 #include "components/autofill/core/common/password_generation_util.h" | 16 #include "components/autofill/core/common/password_generation_util.h" |
| 17 #include "content/public/renderer/render_frame.h" |
| 17 #include "content/public/renderer/render_view.h" | 18 #include "content/public/renderer/render_view.h" |
| 18 #include "google_apis/gaia/gaia_urls.h" | 19 #include "google_apis/gaia/gaia_urls.h" |
| 19 #include "third_party/WebKit/public/platform/WebVector.h" | 20 #include "third_party/WebKit/public/platform/WebVector.h" |
| 20 #include "third_party/WebKit/public/web/WebDocument.h" | 21 #include "third_party/WebKit/public/web/WebDocument.h" |
| 21 #include "third_party/WebKit/public/web/WebFormElement.h" | 22 #include "third_party/WebKit/public/web/WebFormElement.h" |
| 22 #include "third_party/WebKit/public/web/WebInputElement.h" | 23 #include "third_party/WebKit/public/web/WebInputElement.h" |
| 23 #include "third_party/WebKit/public/web/WebLocalFrame.h" | 24 #include "third_party/WebKit/public/web/WebLocalFrame.h" |
| 24 #include "third_party/WebKit/public/web/WebSecurityOrigin.h" | 25 #include "third_party/WebKit/public/web/WebSecurityOrigin.h" |
| 25 #include "third_party/WebKit/public/web/WebView.h" | 26 #include "third_party/WebKit/public/web/WebView.h" |
| 26 #include "ui/gfx/rect.h" | 27 #include "ui/gfx/rect.h" |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 97 std::vector<blink::WebInputElement>* elements) { | 98 std::vector<blink::WebInputElement>* elements) { |
| 98 for (std::vector<blink::WebInputElement>::iterator it = elements->begin(); | 99 for (std::vector<blink::WebInputElement>::iterator it = elements->begin(); |
| 99 it != elements->end(); ++it) { | 100 it != elements->end(); ++it) { |
| 100 it->setValue(value, true /* sendEvents */); | 101 it->setValue(value, true /* sendEvents */); |
| 101 } | 102 } |
| 102 } | 103 } |
| 103 | 104 |
| 104 } // namespace | 105 } // namespace |
| 105 | 106 |
| 106 PasswordGenerationAgent::PasswordGenerationAgent( | 107 PasswordGenerationAgent::PasswordGenerationAgent( |
| 107 content::RenderView* render_view) | 108 content::RenderFrame* render_frame) |
| 108 : content::RenderViewObserver(render_view), | 109 : content::RenderFrameObserver(render_frame), |
| 109 render_view_(render_view), | |
| 110 password_is_generated_(false), | 110 password_is_generated_(false), |
| 111 password_edited_(false), | 111 password_edited_(false), |
| 112 generation_popup_shown_(false), | 112 generation_popup_shown_(false), |
| 113 editing_popup_shown_(false), | 113 editing_popup_shown_(false), |
| 114 enabled_(password_generation::IsPasswordGenerationEnabled()) { | 114 enabled_(password_generation::IsPasswordGenerationEnabled()) { |
| 115 DVLOG(2) << "Password Generation is " << (enabled_ ? "Enabled" : "Disabled"); | 115 DVLOG(2) << "Password Generation is " << (enabled_ ? "Enabled" : "Disabled"); |
| 116 } | 116 } |
| 117 PasswordGenerationAgent::~PasswordGenerationAgent() {} | 117 PasswordGenerationAgent::~PasswordGenerationAgent() {} |
| 118 | 118 |
| 119 void PasswordGenerationAgent::DidFinishDocumentLoad( | 119 void PasswordGenerationAgent::DidFinishDocumentLoad() { |
| 120 blink::WebLocalFrame* frame) { | 120 if (render_frame()->GetWebFrame()->parent()) |
| 121 return; |
| 122 |
| 121 // In every navigation, the IPC message sent by the password autofill manager | 123 // In every navigation, the IPC message sent by the password autofill manager |
| 122 // to query whether the current form is blacklisted or not happens when the | 124 // to query whether the current form is blacklisted or not happens when the |
| 123 // document load finishes, so we need to clear previous states here before we | 125 // document load finishes, so we need to clear previous states here before we |
| 124 // hear back from the browser. We only clear this state on main frame load | 126 // hear back from the browser. We only clear this state on main frame load |
| 125 // as we don't want subframe loads to clear state that we have received from | 127 // as we don't want subframe loads to clear state that we have received from |
| 126 // the main frame. Note that we assume there is only one account creation | 128 // the main frame. Note that we assume there is only one account creation |
| 127 // form, but there could be multiple password forms in each frame. | 129 // form, but there could be multiple password forms in each frame. |
| 128 if (!frame->parent()) { | 130 not_blacklisted_password_form_origins_.clear(); |
| 129 not_blacklisted_password_form_origins_.clear(); | 131 generation_enabled_forms_.clear(); |
| 130 generation_enabled_forms_.clear(); | 132 generation_element_.reset(); |
| 131 generation_element_.reset(); | 133 possible_account_creation_form_.reset(new PasswordForm()); |
| 132 possible_account_creation_form_.reset(new PasswordForm()); | |
| 133 | 134 |
| 134 // Log statistics after navigation so that we only log once per page. | 135 // Log statistics after navigation so that we only log once per page. |
| 135 if (password_elements_.empty()) { | 136 if (password_elements_.empty()) { |
| 136 password_generation::LogPasswordGenerationEvent( | 137 password_generation::LogPasswordGenerationEvent( |
| 137 password_generation::NO_SIGN_UP_DETECTED); | 138 password_generation::NO_SIGN_UP_DETECTED); |
| 138 } else { | 139 } else { |
| 139 password_generation::LogPasswordGenerationEvent( | 140 password_generation::LogPasswordGenerationEvent( |
| 140 password_generation::SIGN_UP_DETECTED); | 141 password_generation::SIGN_UP_DETECTED); |
| 141 } | 142 } |
| 142 password_elements_.clear(); | 143 password_elements_.clear(); |
| 143 password_is_generated_ = false; | 144 password_is_generated_ = false; |
| 144 if (password_edited_) { | 145 if (password_edited_) { |
| 145 password_generation::LogPasswordGenerationEvent( | 146 password_generation::LogPasswordGenerationEvent( |
| 146 password_generation::PASSWORD_EDITED); | 147 password_generation::PASSWORD_EDITED); |
| 147 } | 148 } |
| 148 password_edited_ = false; | 149 password_edited_ = false; |
| 149 | 150 |
| 150 if (generation_popup_shown_) { | 151 if (generation_popup_shown_) { |
| 151 password_generation::LogPasswordGenerationEvent( | 152 password_generation::LogPasswordGenerationEvent( |
| 152 password_generation::GENERATION_POPUP_SHOWN); | 153 password_generation::GENERATION_POPUP_SHOWN); |
| 153 } | 154 } |
| 154 generation_popup_shown_ = false; | 155 generation_popup_shown_ = false; |
| 155 | 156 |
| 156 if (editing_popup_shown_) { | 157 if (editing_popup_shown_) { |
| 157 password_generation::LogPasswordGenerationEvent( | 158 password_generation::LogPasswordGenerationEvent( |
| 158 password_generation::EDITING_POPUP_SHOWN); | 159 password_generation::EDITING_POPUP_SHOWN); |
| 159 } | |
| 160 editing_popup_shown_ = false; | |
| 161 } | 160 } |
| 161 editing_popup_shown_ = false; |
| 162 } | 162 } |
| 163 | 163 |
| 164 void PasswordGenerationAgent::OnDynamicFormsSeen(blink::WebLocalFrame* frame) { | 164 void PasswordGenerationAgent::OnDynamicFormsSeen() { |
| 165 FindPossibleGenerationForm(frame); | 165 FindPossibleGenerationForm(); |
| 166 } | 166 } |
| 167 | 167 |
| 168 void PasswordGenerationAgent::DidFinishLoad(blink::WebLocalFrame* frame) { | 168 void PasswordGenerationAgent::DidFinishLoad() { |
| 169 FindPossibleGenerationForm(frame); | 169 FindPossibleGenerationForm(); |
| 170 } | 170 } |
| 171 | 171 |
| 172 void PasswordGenerationAgent::FindPossibleGenerationForm( | 172 void PasswordGenerationAgent::FindPossibleGenerationForm() { |
| 173 blink::WebLocalFrame* frame) { | |
| 174 if (!enabled_) | 173 if (!enabled_) |
| 175 return; | 174 return; |
| 176 | 175 |
| 177 // We don't want to generate passwords if the browser won't store or sync | 176 // We don't want to generate passwords if the browser won't store or sync |
| 178 // them. | 177 // them. |
| 179 if (!ShouldAnalyzeDocument(frame->document())) | 178 if (!ShouldAnalyzeDocument()) |
| 180 return; | 179 return; |
| 181 | 180 |
| 182 // If we have already found a signup form for this page, no need to continue. | 181 // If we have already found a signup form for this page, no need to continue. |
| 183 if (!password_elements_.empty()) | 182 if (!password_elements_.empty()) |
| 184 return; | 183 return; |
| 185 | 184 |
| 186 blink::WebVector<blink::WebFormElement> forms; | 185 blink::WebVector<blink::WebFormElement> forms; |
| 187 frame->document().forms(forms); | 186 render_frame()->GetWebFrame()->document().forms(forms); |
| 188 for (size_t i = 0; i < forms.size(); ++i) { | 187 for (size_t i = 0; i < forms.size(); ++i) { |
| 189 if (forms[i].isNull()) | 188 if (forms[i].isNull()) |
| 190 continue; | 189 continue; |
| 191 | 190 |
| 192 // If we can't get a valid PasswordForm, we skip this form because the | 191 // If we can't get a valid PasswordForm, we skip this form because the |
| 193 // the password won't get saved even if we generate it. | 192 // the password won't get saved even if we generate it. |
| 194 scoped_ptr<PasswordForm> password_form( | 193 scoped_ptr<PasswordForm> password_form( |
| 195 CreatePasswordForm(forms[i])); | 194 CreatePasswordForm(forms[i])); |
| 196 if (!password_form.get()) { | 195 if (!password_form.get()) { |
| 197 DVLOG(2) << "Skipping form as it would not be saved"; | 196 DVLOG(2) << "Skipping form as it would not be saved"; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 209 DVLOG(2) << "Account creation form detected"; | 208 DVLOG(2) << "Account creation form detected"; |
| 210 password_elements_ = passwords; | 209 password_elements_ = passwords; |
| 211 possible_account_creation_form_.swap(password_form); | 210 possible_account_creation_form_.swap(password_form); |
| 212 DetermineGenerationElement(); | 211 DetermineGenerationElement(); |
| 213 // We assume that there is only one account creation field per URL. | 212 // We assume that there is only one account creation field per URL. |
| 214 return; | 213 return; |
| 215 } | 214 } |
| 216 } | 215 } |
| 217 } | 216 } |
| 218 | 217 |
| 219 bool PasswordGenerationAgent::ShouldAnalyzeDocument( | 218 bool PasswordGenerationAgent::ShouldAnalyzeDocument() const { |
| 220 const blink::WebDocument& document) const { | |
| 221 // Make sure that this security origin is allowed to use password manager. | 219 // Make sure that this security origin is allowed to use password manager. |
| 222 // Generating a password that can't be saved is a bad idea. | 220 // Generating a password that can't be saved is a bad idea. |
| 223 blink::WebSecurityOrigin origin = document.securityOrigin(); | 221 blink::WebSecurityOrigin origin = |
| 222 render_frame()->GetWebFrame()->document().securityOrigin(); |
| 224 if (!origin.canAccessPasswordManager()) { | 223 if (!origin.canAccessPasswordManager()) { |
| 225 DVLOG(1) << "No PasswordManager access"; | 224 DVLOG(1) << "No PasswordManager access"; |
| 226 return false; | 225 return false; |
| 227 } | 226 } |
| 228 | 227 |
| 229 return true; | 228 return true; |
| 230 } | 229 } |
| 231 | 230 |
| 232 bool PasswordGenerationAgent::OnMessageReceived(const IPC::Message& message) { | 231 bool PasswordGenerationAgent::OnMessageReceived(const IPC::Message& message) { |
| 233 bool handled = true; | 232 bool handled = true; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 253 password_is_generated_ = true; | 252 password_is_generated_ = true; |
| 254 password_generation::LogPasswordGenerationEvent( | 253 password_generation::LogPasswordGenerationEvent( |
| 255 password_generation::PASSWORD_ACCEPTED); | 254 password_generation::PASSWORD_ACCEPTED); |
| 256 for (std::vector<blink::WebInputElement>::iterator it = | 255 for (std::vector<blink::WebInputElement>::iterator it = |
| 257 password_elements_.begin(); | 256 password_elements_.begin(); |
| 258 it != password_elements_.end(); ++it) { | 257 it != password_elements_.end(); ++it) { |
| 259 it->setValue(password, true /* sendEvents */); | 258 it->setValue(password, true /* sendEvents */); |
| 260 it->setAutofilled(true); | 259 it->setAutofilled(true); |
| 261 // Advance focus to the next input field. We assume password fields in | 260 // Advance focus to the next input field. We assume password fields in |
| 262 // an account creation form are always adjacent. | 261 // an account creation form are always adjacent. |
| 263 render_view_->GetWebView()->advanceFocus(false); | 262 render_frame()->GetRenderView()->GetWebView()->advanceFocus(false); |
| 264 } | 263 } |
| 265 } | 264 } |
| 266 | 265 |
| 267 void PasswordGenerationAgent::OnAccountCreationFormsDetected( | 266 void PasswordGenerationAgent::OnAccountCreationFormsDetected( |
| 268 const std::vector<autofill::FormData>& forms) { | 267 const std::vector<autofill::FormData>& forms) { |
| 269 generation_enabled_forms_.insert( | 268 generation_enabled_forms_.insert( |
| 270 generation_enabled_forms_.end(), forms.begin(), forms.end()); | 269 generation_enabled_forms_.end(), forms.begin(), forms.end()); |
| 271 DetermineGenerationElement(); | 270 DetermineGenerationElement(); |
| 272 } | 271 } |
| 273 | 272 |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 371 // Password isn't generated and there are fewer than kMaximumOfferSize | 370 // Password isn't generated and there are fewer than kMaximumOfferSize |
| 372 // characters typed, so keep offering the password. Note this function | 371 // characters typed, so keep offering the password. Note this function |
| 373 // will just keep the previous popup if one is already showing. | 372 // will just keep the previous popup if one is already showing. |
| 374 ShowGenerationPopup(); | 373 ShowGenerationPopup(); |
| 375 } | 374 } |
| 376 | 375 |
| 377 return true; | 376 return true; |
| 378 } | 377 } |
| 379 | 378 |
| 380 void PasswordGenerationAgent::ShowGenerationPopup() { | 379 void PasswordGenerationAgent::ShowGenerationPopup() { |
| 381 gfx::RectF bounding_box_scaled = | 380 gfx::RectF bounding_box_scaled = GetScaledBoundingBox( |
| 382 GetScaledBoundingBox(render_view_->GetWebView()->pageScaleFactor(), | 381 render_frame()->GetRenderView()->GetWebView()->pageScaleFactor(), |
| 383 &generation_element_); | 382 &generation_element_); |
| 384 | 383 |
| 385 Send(new AutofillHostMsg_ShowPasswordGenerationPopup( | 384 Send(new AutofillHostMsg_ShowPasswordGenerationPopup( |
| 386 routing_id(), | 385 routing_id(), |
| 387 bounding_box_scaled, | 386 bounding_box_scaled, |
| 388 generation_element_.maxLength(), | 387 generation_element_.maxLength(), |
| 389 *possible_account_creation_form_)); | 388 *possible_account_creation_form_)); |
| 390 | 389 |
| 391 generation_popup_shown_ = true; | 390 generation_popup_shown_ = true; |
| 392 } | 391 } |
| 393 | 392 |
| 394 void PasswordGenerationAgent::ShowEditingPopup() { | 393 void PasswordGenerationAgent::ShowEditingPopup() { |
| 395 gfx::RectF bounding_box_scaled = | 394 gfx::RectF bounding_box_scaled = GetScaledBoundingBox( |
| 396 GetScaledBoundingBox(render_view_->GetWebView()->pageScaleFactor(), | 395 render_frame()->GetRenderView()->GetWebView()->pageScaleFactor(), |
| 397 &generation_element_); | 396 &generation_element_); |
| 398 | 397 |
| 399 Send(new AutofillHostMsg_ShowPasswordEditingPopup( | 398 Send(new AutofillHostMsg_ShowPasswordEditingPopup( |
| 400 routing_id(), | 399 routing_id(), |
| 401 bounding_box_scaled, | 400 bounding_box_scaled, |
| 402 *possible_account_creation_form_)); | 401 *possible_account_creation_form_)); |
| 403 | 402 |
| 404 editing_popup_shown_ = true; | 403 editing_popup_shown_ = true; |
| 405 } | 404 } |
| 406 | 405 |
| 407 void PasswordGenerationAgent::HidePopup() { | 406 void PasswordGenerationAgent::HidePopup() { |
| 408 Send(new AutofillHostMsg_HidePasswordGenerationPopup(routing_id())); | 407 Send(new AutofillHostMsg_HidePasswordGenerationPopup(routing_id())); |
| 409 } | 408 } |
| 410 | 409 |
| 411 } // namespace autofill | 410 } // namespace autofill |
| OLD | NEW |