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 |