Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(48)

Side by Side Diff: components/autofill/content/renderer/password_generation_agent.cc

Issue 2739373002: Password generation logging (Closed)
Patch Set: compilation fix Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 <memory> 7 #include <memory>
8 8
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 19 matching lines...) Expand all
30 #include "third_party/WebKit/public/web/WebFormElement.h" 30 #include "third_party/WebKit/public/web/WebFormElement.h"
31 #include "third_party/WebKit/public/web/WebInputElement.h" 31 #include "third_party/WebKit/public/web/WebInputElement.h"
32 #include "third_party/WebKit/public/web/WebLocalFrame.h" 32 #include "third_party/WebKit/public/web/WebLocalFrame.h"
33 #include "third_party/WebKit/public/web/WebView.h" 33 #include "third_party/WebKit/public/web/WebView.h"
34 #include "ui/gfx/geometry/rect.h" 34 #include "ui/gfx/geometry/rect.h"
35 35
36 namespace autofill { 36 namespace autofill {
37 37
38 namespace { 38 namespace {
39 39
40 using Logger = autofill::SavePasswordProgressLogger;
41
40 // Returns true if we think that this form is for account creation. |passwords| 42 // Returns true if we think that this form is for account creation. |passwords|
41 // is filled with the password field(s) in the form. 43 // is filled with the password field(s) in the form.
42 bool GetAccountCreationPasswordFields( 44 bool GetAccountCreationPasswordFields(
43 const std::vector<blink::WebFormControlElement>& control_elements, 45 const std::vector<blink::WebFormControlElement>& control_elements,
44 std::vector<blink::WebInputElement>* passwords) { 46 std::vector<blink::WebInputElement>* passwords) {
45 for (size_t i = 0; i < control_elements.size(); i++) { 47 for (size_t i = 0; i < control_elements.size(); i++) {
46 const blink::WebInputElement* input_element = 48 const blink::WebInputElement* input_element =
47 toWebInputElement(&control_elements[i]); 49 toWebInputElement(&control_elements[i]);
48 if (input_element && input_element->isTextField()) { 50 if (input_element && input_element->isTextField()) {
49 if (input_element->isPasswordField()) 51 if (input_element->isPasswordField())
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 : content::RenderFrameObserver(render_frame), 137 : content::RenderFrameObserver(render_frame),
136 password_is_generated_(false), 138 password_is_generated_(false),
137 is_manually_triggered_(false), 139 is_manually_triggered_(false),
138 password_edited_(false), 140 password_edited_(false),
139 generation_popup_shown_(false), 141 generation_popup_shown_(false),
140 editing_popup_shown_(false), 142 editing_popup_shown_(false),
141 enabled_(password_generation::IsPasswordGenerationEnabled()), 143 enabled_(password_generation::IsPasswordGenerationEnabled()),
142 form_classifier_enabled_(false), 144 form_classifier_enabled_(false),
143 password_agent_(password_agent), 145 password_agent_(password_agent),
144 binding_(this) { 146 binding_(this) {
145 VLOG(2) << "Password Generation is " << (enabled_ ? "Enabled" : "Disabled"); 147 LogBoolean(Logger::STRING_GENERATION_RENDERER_ENABLED, enabled_);
146 // PasswordGenerationAgent is guaranteed to outlive |render_frame|. 148 // PasswordGenerationAgent is guaranteed to outlive |render_frame|.
147 render_frame->GetInterfaceRegistry()->AddInterface(base::Bind( 149 render_frame->GetInterfaceRegistry()->AddInterface(base::Bind(
148 &PasswordGenerationAgent::BindRequest, base::Unretained(this))); 150 &PasswordGenerationAgent::BindRequest, base::Unretained(this)));
149 } 151 }
150 PasswordGenerationAgent::~PasswordGenerationAgent() {} 152 PasswordGenerationAgent::~PasswordGenerationAgent() {}
151 153
152 void PasswordGenerationAgent::BindRequest( 154 void PasswordGenerationAgent::BindRequest(
153 mojom::PasswordGenerationAgentRequest request) { 155 mojom::PasswordGenerationAgentRequest request) {
154 binding_.Bind(std::move(request)); 156 binding_.Bind(std::move(request));
155 } 157 }
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 render_frame()->GetWebFrame()->document().forms(forms); 253 render_frame()->GetWebFrame()->document().forms(forms);
252 for (size_t i = 0; i < forms.size(); ++i) { 254 for (size_t i = 0; i < forms.size(); ++i) {
253 if (forms[i].isNull()) 255 if (forms[i].isNull())
254 continue; 256 continue;
255 257
256 // If we can't get a valid PasswordForm, we skip this form because the 258 // If we can't get a valid PasswordForm, we skip this form because the
257 // the password won't get saved even if we generate it. 259 // the password won't get saved even if we generate it.
258 std::unique_ptr<PasswordForm> password_form( 260 std::unique_ptr<PasswordForm> password_form(
259 CreatePasswordFormFromWebForm(forms[i], nullptr, nullptr)); 261 CreatePasswordFormFromWebForm(forms[i], nullptr, nullptr));
260 if (!password_form.get()) { 262 if (!password_form.get()) {
261 VLOG(2) << "Skipping form as it would not be saved"; 263 LogMessage(Logger::STRING_GENERATION_RENDERER_INVALID_PASSWORD_FORM);
262 continue; 264 continue;
263 } 265 }
264 266
265 // Do not generate password for GAIA since it is used to retrieve the 267 // Do not generate password for GAIA since it is used to retrieve the
266 // generated paswords. 268 // generated paswords.
267 GURL realm(password_form->signon_realm); 269 GURL realm(password_form->signon_realm);
268 if (realm == GaiaUrls::GetInstance()->gaia_login_form_realm()) 270 if (realm == GaiaUrls::GetInstance()->gaia_login_form_realm())
269 continue; 271 continue;
270 272
271 std::vector<blink::WebInputElement> passwords; 273 std::vector<blink::WebInputElement> passwords;
272 if (GetAccountCreationPasswordFields( 274 if (GetAccountCreationPasswordFields(
273 form_util::ExtractAutofillableElementsInForm(forms[i]), 275 form_util::ExtractAutofillableElementsInForm(forms[i]),
274 &passwords)) { 276 &passwords)) {
275 if (form_classifier_enabled_) 277 if (form_classifier_enabled_)
276 RunFormClassifierAndSaveVote(forms[i], *password_form); 278 RunFormClassifierAndSaveVote(forms[i], *password_form);
277 AccountCreationFormData ac_form_data( 279 AccountCreationFormData ac_form_data(
278 make_linked_ptr(password_form.release()), passwords); 280 make_linked_ptr(password_form.release()), passwords);
279 possible_account_creation_forms_.push_back(ac_form_data); 281 possible_account_creation_forms_.push_back(ac_form_data);
280 } 282 }
281 } 283 }
282 284
283 if (!possible_account_creation_forms_.empty()) { 285 if (!possible_account_creation_forms_.empty()) {
284 VLOG(2) << possible_account_creation_forms_.size() 286 LogNumber(
285 << " possible account creation forms deteceted"; 287 Logger::STRING_GENERATION_RENDERER_POSSIBLE_ACCOUNT_CREATION_FORMS,
288 possible_account_creation_forms_.size());
286 DetermineGenerationElement(); 289 DetermineGenerationElement();
287 } 290 }
288 } 291 }
289 292
290 bool PasswordGenerationAgent::ShouldAnalyzeDocument() const { 293 bool PasswordGenerationAgent::ShouldAnalyzeDocument() {
291 // Make sure that this security origin is allowed to use password manager. 294 // Make sure that this security origin is allowed to use password manager.
292 // Generating a password that can't be saved is a bad idea. 295 // Generating a password that can't be saved is a bad idea.
293 if (!render_frame() || 296 if (!render_frame() ||
294 !render_frame() 297 !render_frame()
295 ->GetWebFrame() 298 ->GetWebFrame()
296 ->document() 299 ->document()
297 .getSecurityOrigin() 300 .getSecurityOrigin()
298 .canAccessPasswordManager()) { 301 .canAccessPasswordManager()) {
299 VLOG(1) << "No PasswordManager access"; 302 LogMessage(Logger::STRING_GENERATION_RENDERER_NO_PASSWORD_MANAGER_ACCESS);
300 return false; 303 return false;
301 } 304 }
302 305
303 return true; 306 return true;
304 } 307 }
305 308
306 void PasswordGenerationAgent::FormNotBlacklisted(const PasswordForm& form) { 309 void PasswordGenerationAgent::FormNotBlacklisted(const PasswordForm& form) {
307 not_blacklisted_password_form_origins_.push_back(form.origin); 310 not_blacklisted_password_form_origins_.push_back(form.origin);
308 DetermineGenerationElement(); 311 DetermineGenerationElement();
309 } 312 }
310 313
311 void PasswordGenerationAgent::GeneratedPasswordAccepted( 314 void PasswordGenerationAgent::GeneratedPasswordAccepted(
312 const base::string16& password) { 315 const base::string16& password) {
313 password_is_generated_ = true; 316 password_is_generated_ = true;
314 password_generation::LogPasswordGenerationEvent( 317 password_generation::LogPasswordGenerationEvent(
315 password_generation::PASSWORD_ACCEPTED); 318 password_generation::PASSWORD_ACCEPTED);
319 LogMessage(Logger::STRING_GENERATION_RENDERER_GENERATED_PASSWORD_ACCEPTED);
316 for (auto& password_element : generation_form_data_->password_elements) { 320 for (auto& password_element : generation_form_data_->password_elements) {
317 password_element.setValue(blink::WebString::fromUTF16(password), 321 password_element.setValue(blink::WebString::fromUTF16(password),
318 true /* sendEvents */); 322 true /* sendEvents */);
319 // setValue() above may have resulted in JavaScript closing the frame. 323 // setValue() above may have resulted in JavaScript closing the frame.
320 if (!render_frame()) 324 if (!render_frame())
321 return; 325 return;
322 password_element.setAutofilled(true); 326 password_element.setAutofilled(true);
323 // Needed to notify password_autofill_agent that the content of the field 327 // Needed to notify password_autofill_agent that the content of the field
324 // has changed. Without this we will overwrite the generated 328 // has changed. Without this we will overwrite the generated
325 // password with an Autofilled password when saving. 329 // password with an Autofilled password when saving.
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 365
362 void PasswordGenerationAgent::FoundFormsEligibleForGeneration( 366 void PasswordGenerationAgent::FoundFormsEligibleForGeneration(
363 const std::vector<PasswordFormGenerationData>& forms) { 367 const std::vector<PasswordFormGenerationData>& forms) {
364 generation_enabled_forms_.insert(generation_enabled_forms_.end(), 368 generation_enabled_forms_.insert(generation_enabled_forms_.end(),
365 forms.begin(), forms.end()); 369 forms.begin(), forms.end());
366 DetermineGenerationElement(); 370 DetermineGenerationElement();
367 } 371 }
368 372
369 void PasswordGenerationAgent::DetermineGenerationElement() { 373 void PasswordGenerationAgent::DetermineGenerationElement() {
370 if (generation_form_data_) { 374 if (generation_form_data_) {
371 VLOG(2) << "Account creation form already found"; 375 LogMessage(Logger::STRING_GENERATION_RENDERER_FORM_ALREADY_FOUND);
372 return; 376 return;
373 } 377 }
374 378
375 // Make sure local heuristics have identified a possible account creation 379 // Make sure local heuristics have identified a possible account creation
376 // form. 380 // form.
377 if (possible_account_creation_forms_.empty()) { 381 if (possible_account_creation_forms_.empty()) {
378 VLOG(2) << "Local hueristics have not detected a possible account " 382 LogMessage(Logger::STRING_GENERATION_RENDERER_NO_POSSIBLE_CREATION_FORMS);
379 << "creation form";
380 return; 383 return;
381 } 384 }
382 385
383 // Note that no messages will be sent if this feature is disabled 386 // Note that no messages will be sent if this feature is disabled
384 // (e.g. password saving is disabled). 387 // (e.g. password saving is disabled).
385 for (auto& possible_form_data : possible_account_creation_forms_) { 388 for (auto& possible_form_data : possible_account_creation_forms_) {
386 PasswordForm* possible_password_form = possible_form_data.form.get(); 389 PasswordForm* possible_password_form = possible_form_data.form.get();
387 const PasswordFormGenerationData* generation_data = nullptr; 390 const PasswordFormGenerationData* generation_data = nullptr;
388 if (base::CommandLine::ForCurrentProcess()->HasSwitch( 391 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
389 switches::kLocalHeuristicsOnlyForPasswordGeneration)) { 392 switches::kLocalHeuristicsOnlyForPasswordGeneration)) {
390 VLOG(2) << "Bypassing additional checks."; 393 VLOG(2) << "Bypassing additional checks.";
391 } else if (!ContainsURL(not_blacklisted_password_form_origins_, 394 } else if (!ContainsURL(not_blacklisted_password_form_origins_,
392 possible_password_form->origin)) { 395 possible_password_form->origin)) {
393 VLOG(2) << "Have not received confirmation that password form isn't " 396 LogMessage(Logger::STRING_GENERATION_RENDERER_NOT_BLACKLISTED);
394 << "blacklisted";
395 continue; 397 continue;
396 } else { 398 } else {
397 generation_data = FindFormGenerationData(generation_enabled_forms_, 399 generation_data = FindFormGenerationData(generation_enabled_forms_,
398 *possible_password_form); 400 *possible_password_form);
399 if (!generation_data) { 401 if (!generation_data) {
400 if (AutocompleteAttributesSetForGeneration(*possible_password_form)) { 402 if (AutocompleteAttributesSetForGeneration(*possible_password_form)) {
401 VLOG(2) << "Ignoring lack of Autofill signal due to Autocomplete " 403 LogMessage(Logger::STRING_GENERATION_RENDERER_AUTOCOMPLETE_ATTRIBUTE);
402 << "attributes";
403 password_generation::LogPasswordGenerationEvent( 404 password_generation::LogPasswordGenerationEvent(
404 password_generation::AUTOCOMPLETE_ATTRIBUTES_ENABLED_GENERATION); 405 password_generation::AUTOCOMPLETE_ATTRIBUTES_ENABLED_GENERATION);
405 } else { 406 } else {
406 VLOG(2) 407 LogMessage(Logger::STRING_GENERATION_RENDERER_NO_SERVER_SIGNAL);
407 << "Have not received confirmation from Autofill that form is "
408 << "used for account creation";
409 continue; 408 continue;
410 } 409 }
411 } 410 }
412 } 411 }
413 412 LogMessage(Logger::STRING_GENERATION_RENDERER_ELIGIBLE_FORM_FOUND);
414 VLOG(2) << "Password generation eligible form found";
415 std::vector<blink::WebInputElement> password_elements = 413 std::vector<blink::WebInputElement> password_elements =
416 generation_data 414 generation_data
417 ? FindPasswordElementsForGeneration( 415 ? FindPasswordElementsForGeneration(
418 possible_form_data.password_elements, *generation_data) 416 possible_form_data.password_elements, *generation_data)
419 : possible_form_data.password_elements; 417 : possible_form_data.password_elements;
420 if (password_elements.empty()) { 418 if (password_elements.empty()) {
421 // It might be if JavaScript changes field names. 419 // It might be if JavaScript changes field names.
422 VLOG(2) << "Fields for generation are not found"; 420 LogMessage(Logger::STRING_GENERATION_RENDERER_NO_FIELD_FOUND);
423 return; 421 return;
424 } 422 }
425 generation_form_data_.reset(new AccountCreationFormData( 423 generation_form_data_.reset(new AccountCreationFormData(
426 possible_form_data.form, std::move(password_elements))); 424 possible_form_data.form, std::move(password_elements)));
427 generation_element_ = generation_form_data_->password_elements[0]; 425 generation_element_ = generation_form_data_->password_elements[0];
428 generation_element_.setAttribute("aria-autocomplete", "list"); 426 generation_element_.setAttribute("aria-autocomplete", "list");
429 password_generation::LogPasswordGenerationEvent( 427 password_generation::LogPasswordGenerationEvent(
430 password_generation::GENERATION_AVAILABLE); 428 password_generation::GENERATION_AVAILABLE);
431 possible_account_creation_forms_.clear(); 429 possible_account_creation_forms_.clear();
432 GetPasswordManagerClient()->GenerationAvailableForForm( 430 GetPasswordManagerClient()->GenerationAvailableForForm(
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
515 // will just keep the previous popup if one is already showing. 513 // will just keep the previous popup if one is already showing.
516 ShowGenerationPopup(); 514 ShowGenerationPopup();
517 } 515 }
518 516
519 return true; 517 return true;
520 } 518 }
521 519
522 void PasswordGenerationAgent::ShowGenerationPopup() { 520 void PasswordGenerationAgent::ShowGenerationPopup() {
523 if (!render_frame()) 521 if (!render_frame())
524 return; 522 return;
523 LogMessage(Logger::STRING_GENERATION_RENDERER_SHOW_GENERATION_POPUP);
525 GetPasswordManagerClient()->ShowPasswordGenerationPopup( 524 GetPasswordManagerClient()->ShowPasswordGenerationPopup(
526 render_frame()->GetRenderView()->ElementBoundsInWindow( 525 render_frame()->GetRenderView()->ElementBoundsInWindow(
527 generation_element_), 526 generation_element_),
528 generation_element_.maxLength(), 527 generation_element_.maxLength(),
529 generation_element_.nameForAutofill().utf16(), is_manually_triggered_, 528 generation_element_.nameForAutofill().utf16(), is_manually_triggered_,
530 *generation_form_data_->form); 529 *generation_form_data_->form);
531 generation_popup_shown_ = true; 530 generation_popup_shown_ = true;
532 } 531 }
533 532
534 void PasswordGenerationAgent::ShowEditingPopup() { 533 void PasswordGenerationAgent::ShowEditingPopup() {
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
594 const mojom::PasswordManagerClientAssociatedPtr& 593 const mojom::PasswordManagerClientAssociatedPtr&
595 PasswordGenerationAgent::GetPasswordManagerClient() { 594 PasswordGenerationAgent::GetPasswordManagerClient() {
596 if (!password_manager_client_) { 595 if (!password_manager_client_) {
597 render_frame()->GetRemoteAssociatedInterfaces()->GetInterface( 596 render_frame()->GetRemoteAssociatedInterfaces()->GetInterface(
598 &password_manager_client_); 597 &password_manager_client_);
599 } 598 }
600 599
601 return password_manager_client_; 600 return password_manager_client_;
602 } 601 }
603 602
603 void PasswordGenerationAgent::LogMessage(Logger::StringID message_id) {
604 if (!password_agent_->logging_state_active())
605 return;
606 RendererSavePasswordProgressLogger logger(GetPasswordManagerDriver().get());
607 logger.LogMessage(message_id);
608 }
609
610 void PasswordGenerationAgent::LogBoolean(Logger::StringID message_id,
611 bool truth_value) {
612 if (!password_agent_->logging_state_active())
613 return;
614 RendererSavePasswordProgressLogger logger(GetPasswordManagerDriver().get());
615 logger.LogBoolean(message_id, truth_value);
616 }
617
618 void PasswordGenerationAgent::LogNumber(Logger::StringID message_id,
619 int number) {
620 if (!password_agent_->logging_state_active())
621 return;
622 RendererSavePasswordProgressLogger logger(GetPasswordManagerDriver().get());
623 logger.LogNumber(message_id, number);
624 }
625
604 } // namespace autofill 626 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698