| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 <stdarg.h> | 5 #include <stdarg.h> |
| 6 | 6 |
| 7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
| 8 #include "base/stl_util.h" | 8 #include "base/stl_util.h" |
| 9 #include "base/string_util.h" | 9 #include "base/string_util.h" |
| 10 #include "base/stringprintf.h" | 10 #include "base/stringprintf.h" |
| (...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 389 PasswordForm form_isc_; | 389 PasswordForm form_isc_; |
| 390 }; | 390 }; |
| 391 | 391 |
| 392 TEST_F(NativeBackendGnomeTest, BasicAddLogin) { | 392 TEST_F(NativeBackendGnomeTest, BasicAddLogin) { |
| 393 // Pretend that the migration has already taken place. | 393 // Pretend that the migration has already taken place. |
| 394 profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true); | 394 profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true); |
| 395 | 395 |
| 396 NativeBackendGnome backend(42, profile_.GetPrefs()); | 396 NativeBackendGnome backend(42, profile_.GetPrefs()); |
| 397 backend.Init(); | 397 backend.Init(); |
| 398 | 398 |
| 399 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 399 BrowserThread::PostTask( |
| 400 base::IgnoreReturn<bool>(base::Bind( | 400 BrowserThread::DB, FROM_HERE, |
| 401 &NativeBackendGnome::AddLogin, | 401 base::Bind(base::IgnoreResult(&NativeBackendGnome::AddLogin), |
| 402 base::Unretained(&backend), form_google_))); | 402 base::Unretained(&backend), form_google_)); |
| 403 | 403 |
| 404 RunBothThreads(); | 404 RunBothThreads(); |
| 405 | 405 |
| 406 EXPECT_EQ(1u, mock_keyring_items.size()); | 406 EXPECT_EQ(1u, mock_keyring_items.size()); |
| 407 if (mock_keyring_items.size() > 0) | 407 if (mock_keyring_items.size() > 0) |
| 408 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome-42"); | 408 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome-42"); |
| 409 } | 409 } |
| 410 | 410 |
| 411 TEST_F(NativeBackendGnomeTest, BasicListLogins) { | 411 TEST_F(NativeBackendGnomeTest, BasicListLogins) { |
| 412 // Pretend that the migration has already taken place. | 412 // Pretend that the migration has already taken place. |
| 413 profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true); | 413 profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true); |
| 414 | 414 |
| 415 NativeBackendGnome backend(42, profile_.GetPrefs()); | 415 NativeBackendGnome backend(42, profile_.GetPrefs()); |
| 416 backend.Init(); | 416 backend.Init(); |
| 417 | 417 |
| 418 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 418 BrowserThread::PostTask( |
| 419 base::IgnoreReturn<bool>(base::Bind( | 419 BrowserThread::DB, FROM_HERE, |
| 420 &NativeBackendGnome::AddLogin, | 420 base::Bind(base::IgnoreResult( &NativeBackendGnome::AddLogin), |
| 421 base::Unretained(&backend), form_google_))); | 421 base::Unretained(&backend), form_google_)); |
| 422 | 422 |
| 423 std::vector<PasswordForm*> form_list; | 423 std::vector<PasswordForm*> form_list; |
| 424 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 424 BrowserThread::PostTask( |
| 425 base::IgnoreReturn<bool>(base::Bind( | 425 BrowserThread::DB, FROM_HERE, |
| 426 &NativeBackendGnome::GetAutofillableLogins, | 426 base::Bind( |
| 427 base::Unretained(&backend), &form_list))); | 427 base::IgnoreResult(&NativeBackendGnome::GetAutofillableLogins), |
| 428 base::Unretained(&backend), &form_list)); |
| 428 | 429 |
| 429 RunBothThreads(); | 430 RunBothThreads(); |
| 430 | 431 |
| 431 // Quick check that we got something back. | 432 // Quick check that we got something back. |
| 432 EXPECT_EQ(1u, form_list.size()); | 433 EXPECT_EQ(1u, form_list.size()); |
| 433 STLDeleteElements(&form_list); | 434 STLDeleteElements(&form_list); |
| 434 | 435 |
| 435 EXPECT_EQ(1u, mock_keyring_items.size()); | 436 EXPECT_EQ(1u, mock_keyring_items.size()); |
| 436 if (mock_keyring_items.size() > 0) | 437 if (mock_keyring_items.size() > 0) |
| 437 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome-42"); | 438 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome-42"); |
| 438 } | 439 } |
| 439 | 440 |
| 440 TEST_F(NativeBackendGnomeTest, BasicRemoveLogin) { | 441 TEST_F(NativeBackendGnomeTest, BasicRemoveLogin) { |
| 441 // Pretend that the migration has already taken place. | 442 // Pretend that the migration has already taken place. |
| 442 profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true); | 443 profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true); |
| 443 | 444 |
| 444 NativeBackendGnome backend(42, profile_.GetPrefs()); | 445 NativeBackendGnome backend(42, profile_.GetPrefs()); |
| 445 backend.Init(); | 446 backend.Init(); |
| 446 | 447 |
| 447 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 448 BrowserThread::PostTask( |
| 448 base::IgnoreReturn<bool>(base::Bind( | 449 BrowserThread::DB, FROM_HERE, |
| 449 &NativeBackendGnome::AddLogin, | 450 base::Bind(base::IgnoreResult(&NativeBackendGnome::AddLogin), |
| 450 base::Unretained(&backend), form_google_))); | 451 base::Unretained(&backend), form_google_)); |
| 451 | 452 |
| 452 RunBothThreads(); | 453 RunBothThreads(); |
| 453 | 454 |
| 454 EXPECT_EQ(1u, mock_keyring_items.size()); | 455 EXPECT_EQ(1u, mock_keyring_items.size()); |
| 455 if (mock_keyring_items.size() > 0) | 456 if (mock_keyring_items.size() > 0) |
| 456 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome-42"); | 457 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome-42"); |
| 457 | 458 |
| 458 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 459 BrowserThread::PostTask( |
| 459 base::IgnoreReturn<bool>(base::Bind( | 460 BrowserThread::DB, FROM_HERE, |
| 460 &NativeBackendGnome::RemoveLogin, | 461 base::Bind(base::IgnoreResult(&NativeBackendGnome::RemoveLogin), |
| 461 base::Unretained(&backend), form_google_))); | 462 base::Unretained(&backend), form_google_)); |
| 462 | 463 |
| 463 RunBothThreads(); | 464 RunBothThreads(); |
| 464 | 465 |
| 465 EXPECT_EQ(0u, mock_keyring_items.size()); | 466 EXPECT_EQ(0u, mock_keyring_items.size()); |
| 466 } | 467 } |
| 467 | 468 |
| 468 TEST_F(NativeBackendGnomeTest, RemoveNonexistentLogin) { | 469 TEST_F(NativeBackendGnomeTest, RemoveNonexistentLogin) { |
| 469 // Pretend that the migration has already taken place. | 470 // Pretend that the migration has already taken place. |
| 470 profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true); | 471 profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true); |
| 471 | 472 |
| 472 NativeBackendGnome backend(42, profile_.GetPrefs()); | 473 NativeBackendGnome backend(42, profile_.GetPrefs()); |
| 473 backend.Init(); | 474 backend.Init(); |
| 474 | 475 |
| 475 // First add an unrelated login. | 476 // First add an unrelated login. |
| 476 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 477 BrowserThread::PostTask( |
| 477 base::IgnoreReturn<bool>(base::Bind( | 478 BrowserThread::DB, FROM_HERE, |
| 478 &NativeBackendGnome::AddLogin, | 479 base::Bind(base::IgnoreResult(&NativeBackendGnome::AddLogin), |
| 479 base::Unretained(&backend), form_google_))); | 480 base::Unretained(&backend), form_google_)); |
| 480 | 481 |
| 481 RunBothThreads(); | 482 RunBothThreads(); |
| 482 | 483 |
| 483 EXPECT_EQ(1u, mock_keyring_items.size()); | 484 EXPECT_EQ(1u, mock_keyring_items.size()); |
| 484 if (mock_keyring_items.size() > 0) | 485 if (mock_keyring_items.size() > 0) |
| 485 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome-42"); | 486 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome-42"); |
| 486 | 487 |
| 487 // Attempt to remove a login that doesn't exist. | 488 // Attempt to remove a login that doesn't exist. |
| 488 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 489 BrowserThread::PostTask( |
| 489 base::IgnoreReturn<bool>(base::Bind( | 490 BrowserThread::DB, FROM_HERE, |
| 490 &NativeBackendGnome::RemoveLogin, | 491 base::Bind(base::IgnoreResult(&NativeBackendGnome::RemoveLogin), |
| 491 base::Unretained(&backend), form_isc_))); | 492 base::Unretained(&backend), form_isc_)); |
| 492 | 493 |
| 493 // Make sure we can still get the first form back. | 494 // Make sure we can still get the first form back. |
| 494 std::vector<PasswordForm*> form_list; | 495 std::vector<PasswordForm*> form_list; |
| 495 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 496 BrowserThread::PostTask( |
| 496 base::IgnoreReturn<bool>(base::Bind( | 497 BrowserThread::DB, FROM_HERE, |
| 497 &NativeBackendGnome::GetAutofillableLogins, | 498 base::Bind( |
| 498 base::Unretained(&backend), &form_list))); | 499 base::IgnoreResult(&NativeBackendGnome::GetAutofillableLogins), |
| 500 base::Unretained(&backend), &form_list)); |
| 499 | 501 |
| 500 RunBothThreads(); | 502 RunBothThreads(); |
| 501 | 503 |
| 502 // Quick check that we got something back. | 504 // Quick check that we got something back. |
| 503 EXPECT_EQ(1u, form_list.size()); | 505 EXPECT_EQ(1u, form_list.size()); |
| 504 STLDeleteElements(&form_list); | 506 STLDeleteElements(&form_list); |
| 505 | 507 |
| 506 EXPECT_EQ(1u, mock_keyring_items.size()); | 508 EXPECT_EQ(1u, mock_keyring_items.size()); |
| 507 if (mock_keyring_items.size() > 0) | 509 if (mock_keyring_items.size() > 0) |
| 508 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome-42"); | 510 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome-42"); |
| 509 } | 511 } |
| 510 | 512 |
| 511 TEST_F(NativeBackendGnomeTest, AddDuplicateLogin) { | 513 TEST_F(NativeBackendGnomeTest, AddDuplicateLogin) { |
| 512 // Pretend that the migration has already taken place. | 514 // Pretend that the migration has already taken place. |
| 513 profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true); | 515 profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true); |
| 514 | 516 |
| 515 NativeBackendGnome backend(42, profile_.GetPrefs()); | 517 NativeBackendGnome backend(42, profile_.GetPrefs()); |
| 516 backend.Init(); | 518 backend.Init(); |
| 517 | 519 |
| 518 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 520 BrowserThread::PostTask( |
| 519 base::IgnoreReturn<bool>(base::Bind( | 521 BrowserThread::DB, FROM_HERE, |
| 520 &NativeBackendGnome::AddLogin, | 522 base::Bind(base::IgnoreResult(&NativeBackendGnome::AddLogin), |
| 521 base::Unretained(&backend), form_google_))); | 523 base::Unretained(&backend), form_google_)); |
| 522 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 524 BrowserThread::PostTask( |
| 523 base::IgnoreReturn<bool>(base::Bind( | 525 BrowserThread::DB, FROM_HERE, |
| 524 &NativeBackendGnome::AddLogin, | 526 base::Bind(base::IgnoreResult(&NativeBackendGnome::AddLogin), |
| 525 base::Unretained(&backend), form_google_))); | 527 base::Unretained(&backend), form_google_)); |
| 526 | 528 |
| 527 RunBothThreads(); | 529 RunBothThreads(); |
| 528 | 530 |
| 529 EXPECT_EQ(1u, mock_keyring_items.size()); | 531 EXPECT_EQ(1u, mock_keyring_items.size()); |
| 530 if (mock_keyring_items.size() > 0) | 532 if (mock_keyring_items.size() > 0) |
| 531 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome-42"); | 533 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome-42"); |
| 532 } | 534 } |
| 533 | 535 |
| 534 TEST_F(NativeBackendGnomeTest, ListLoginsAppends) { | 536 TEST_F(NativeBackendGnomeTest, ListLoginsAppends) { |
| 535 // Pretend that the migration has already taken place. | 537 // Pretend that the migration has already taken place. |
| 536 profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true); | 538 profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true); |
| 537 | 539 |
| 538 NativeBackendGnome backend(42, profile_.GetPrefs()); | 540 NativeBackendGnome backend(42, profile_.GetPrefs()); |
| 539 backend.Init(); | 541 backend.Init(); |
| 540 | 542 |
| 541 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 543 BrowserThread::PostTask( |
| 542 base::IgnoreReturn<bool>(base::Bind( | 544 BrowserThread::DB, FROM_HERE, |
| 543 &NativeBackendGnome::AddLogin, | 545 base::Bind(base::IgnoreResult(&NativeBackendGnome::AddLogin), |
| 544 base::Unretained(&backend), form_google_))); | 546 base::Unretained(&backend), form_google_)); |
| 545 | 547 |
| 546 // Send the same request twice with the same list both times. | 548 // Send the same request twice with the same list both times. |
| 547 std::vector<PasswordForm*> form_list; | 549 std::vector<PasswordForm*> form_list; |
| 548 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 550 BrowserThread::PostTask( |
| 549 base::IgnoreReturn<bool>(base::Bind( | 551 BrowserThread::DB, FROM_HERE, |
| 550 &NativeBackendGnome::GetAutofillableLogins, | 552 base::Bind( |
| 551 base::Unretained(&backend), &form_list))); | 553 base::IgnoreResult(&NativeBackendGnome::GetAutofillableLogins), |
| 552 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 554 base::Unretained(&backend), &form_list)); |
| 553 base::IgnoreReturn<bool>(base::Bind( | 555 BrowserThread::PostTask( |
| 554 &NativeBackendGnome::GetAutofillableLogins, | 556 BrowserThread::DB, FROM_HERE, |
| 555 base::Unretained(&backend), &form_list))); | 557 base::Bind( |
| 558 base::IgnoreResult(&NativeBackendGnome::GetAutofillableLogins), |
| 559 base::Unretained(&backend), &form_list)); |
| 556 | 560 |
| 557 RunBothThreads(); | 561 RunBothThreads(); |
| 558 | 562 |
| 559 // Quick check that we got two results back. | 563 // Quick check that we got two results back. |
| 560 EXPECT_EQ(2u, form_list.size()); | 564 EXPECT_EQ(2u, form_list.size()); |
| 561 STLDeleteElements(&form_list); | 565 STLDeleteElements(&form_list); |
| 562 | 566 |
| 563 EXPECT_EQ(1u, mock_keyring_items.size()); | 567 EXPECT_EQ(1u, mock_keyring_items.size()); |
| 564 if (mock_keyring_items.size() > 0) | 568 if (mock_keyring_items.size() > 0) |
| 565 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome-42"); | 569 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome-42"); |
| 566 } | 570 } |
| 567 | 571 |
| 568 // TODO(mdm): add more basic (i.e. non-migration) tests here at some point. | 572 // TODO(mdm): add more basic (i.e. non-migration) tests here at some point. |
| 569 | 573 |
| 570 TEST_F(NativeBackendGnomeTest, MigrateOneLogin) { | 574 TEST_F(NativeBackendGnomeTest, MigrateOneLogin) { |
| 571 // Reject attempts to migrate so we can populate the store. | 575 // Reject attempts to migrate so we can populate the store. |
| 572 mock_keyring_reject_local_ids = true; | 576 mock_keyring_reject_local_ids = true; |
| 573 | 577 |
| 574 { | 578 { |
| 575 NativeBackendGnome backend(42, profile_.GetPrefs()); | 579 NativeBackendGnome backend(42, profile_.GetPrefs()); |
| 576 backend.Init(); | 580 backend.Init(); |
| 577 | 581 |
| 578 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 582 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, |
| 579 base::IgnoreReturn<bool>(base::Bind( | 583 base::Bind(base::IgnoreResult(&NativeBackendGnome::AddLogin), |
| 580 &NativeBackendGnome::AddLogin, | 584 base::Unretained(&backend), form_google_)); |
| 581 base::Unretained(&backend), form_google_))); | |
| 582 | 585 |
| 583 // Make sure we can get the form back even when migration is failing. | 586 // Make sure we can get the form back even when migration is failing. |
| 584 std::vector<PasswordForm*> form_list; | 587 std::vector<PasswordForm*> form_list; |
| 585 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 588 BrowserThread::PostTask( |
| 586 base::IgnoreReturn<bool>(base::Bind( | 589 BrowserThread::DB, FROM_HERE, |
| 587 &NativeBackendGnome::GetAutofillableLogins, | 590 base::Bind( |
| 588 base::Unretained(&backend), &form_list))); | 591 base::IgnoreResult(&NativeBackendGnome::GetAutofillableLogins), |
| 592 base::Unretained(&backend), &form_list)); |
| 589 | 593 |
| 590 RunBothThreads(); | 594 RunBothThreads(); |
| 591 | 595 |
| 592 // Quick check that we got something back. | 596 // Quick check that we got something back. |
| 593 EXPECT_EQ(1u, form_list.size()); | 597 EXPECT_EQ(1u, form_list.size()); |
| 594 STLDeleteElements(&form_list); | 598 STLDeleteElements(&form_list); |
| 595 } | 599 } |
| 596 | 600 |
| 597 EXPECT_EQ(1u, mock_keyring_items.size()); | 601 EXPECT_EQ(1u, mock_keyring_items.size()); |
| 598 if (mock_keyring_items.size() > 0) | 602 if (mock_keyring_items.size() > 0) |
| 599 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome"); | 603 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome"); |
| 600 | 604 |
| 601 // Now allow the migration. | 605 // Now allow the migration. |
| 602 mock_keyring_reject_local_ids = false; | 606 mock_keyring_reject_local_ids = false; |
| 603 | 607 |
| 604 { | 608 { |
| 605 NativeBackendGnome backend(42, profile_.GetPrefs()); | 609 NativeBackendGnome backend(42, profile_.GetPrefs()); |
| 606 backend.Init(); | 610 backend.Init(); |
| 607 | 611 |
| 608 // This should not trigger migration because there will be no results. | 612 // This should not trigger migration because there will be no results. |
| 609 std::vector<PasswordForm*> form_list; | 613 std::vector<PasswordForm*> form_list; |
| 610 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 614 BrowserThread::PostTask( |
| 611 base::IgnoreReturn<bool>(base::Bind( | 615 BrowserThread::DB, FROM_HERE, |
| 612 &NativeBackendGnome::GetBlacklistLogins, | 616 base::Bind(base::IgnoreResult(&NativeBackendGnome::GetBlacklistLogins), |
| 613 base::Unretained(&backend), &form_list))); | 617 base::Unretained(&backend), &form_list)); |
| 614 | 618 |
| 615 RunBothThreads(); | 619 RunBothThreads(); |
| 616 | 620 |
| 617 // Check that we got nothing back. | 621 // Check that we got nothing back. |
| 618 EXPECT_EQ(0u, form_list.size()); | 622 EXPECT_EQ(0u, form_list.size()); |
| 619 STLDeleteElements(&form_list); | 623 STLDeleteElements(&form_list); |
| 620 } | 624 } |
| 621 | 625 |
| 622 // Check that the keyring is unmodified. | 626 // Check that the keyring is unmodified. |
| 623 EXPECT_EQ(1u, mock_keyring_items.size()); | 627 EXPECT_EQ(1u, mock_keyring_items.size()); |
| 624 if (mock_keyring_items.size() > 0) | 628 if (mock_keyring_items.size() > 0) |
| 625 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome"); | 629 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome"); |
| 626 | 630 |
| 627 // Check that we haven't set the persistent preference. | 631 // Check that we haven't set the persistent preference. |
| 628 EXPECT_FALSE( | 632 EXPECT_FALSE( |
| 629 profile_.GetPrefs()->GetBoolean(prefs::kPasswordsUseLocalProfileId)); | 633 profile_.GetPrefs()->GetBoolean(prefs::kPasswordsUseLocalProfileId)); |
| 630 | 634 |
| 631 { | 635 { |
| 632 NativeBackendGnome backend(42, profile_.GetPrefs()); | 636 NativeBackendGnome backend(42, profile_.GetPrefs()); |
| 633 backend.Init(); | 637 backend.Init(); |
| 634 | 638 |
| 635 // Trigger the migration by looking something up. | 639 // Trigger the migration by looking something up. |
| 636 std::vector<PasswordForm*> form_list; | 640 std::vector<PasswordForm*> form_list; |
| 637 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 641 BrowserThread::PostTask( |
| 638 base::IgnoreReturn<bool>(base::Bind( | 642 BrowserThread::DB, FROM_HERE, |
| 639 &NativeBackendGnome::GetAutofillableLogins, | 643 base::Bind( |
| 640 base::Unretained(&backend), &form_list))); | 644 base::IgnoreResult(&NativeBackendGnome::GetAutofillableLogins), |
| 645 base::Unretained(&backend), &form_list)); |
| 641 | 646 |
| 642 RunBothThreads(); | 647 RunBothThreads(); |
| 643 | 648 |
| 644 // Quick check that we got something back. | 649 // Quick check that we got something back. |
| 645 EXPECT_EQ(1u, form_list.size()); | 650 EXPECT_EQ(1u, form_list.size()); |
| 646 STLDeleteElements(&form_list); | 651 STLDeleteElements(&form_list); |
| 647 } | 652 } |
| 648 | 653 |
| 649 EXPECT_EQ(2u, mock_keyring_items.size()); | 654 EXPECT_EQ(2u, mock_keyring_items.size()); |
| 650 if (mock_keyring_items.size() > 0) | 655 if (mock_keyring_items.size() > 0) |
| 651 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome"); | 656 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome"); |
| 652 if (mock_keyring_items.size() > 1) | 657 if (mock_keyring_items.size() > 1) |
| 653 CheckMockKeyringItem(&mock_keyring_items[1], form_google_, "chrome-42"); | 658 CheckMockKeyringItem(&mock_keyring_items[1], form_google_, "chrome-42"); |
| 654 | 659 |
| 655 // Check that we have set the persistent preference. | 660 // Check that we have set the persistent preference. |
| 656 EXPECT_TRUE( | 661 EXPECT_TRUE( |
| 657 profile_.GetPrefs()->GetBoolean(prefs::kPasswordsUseLocalProfileId)); | 662 profile_.GetPrefs()->GetBoolean(prefs::kPasswordsUseLocalProfileId)); |
| 658 } | 663 } |
| 659 | 664 |
| 660 TEST_F(NativeBackendGnomeTest, MigrateToMultipleProfiles) { | 665 TEST_F(NativeBackendGnomeTest, MigrateToMultipleProfiles) { |
| 661 // Reject attempts to migrate so we can populate the store. | 666 // Reject attempts to migrate so we can populate the store. |
| 662 mock_keyring_reject_local_ids = true; | 667 mock_keyring_reject_local_ids = true; |
| 663 | 668 |
| 664 { | 669 { |
| 665 NativeBackendGnome backend(42, profile_.GetPrefs()); | 670 NativeBackendGnome backend(42, profile_.GetPrefs()); |
| 666 backend.Init(); | 671 backend.Init(); |
| 667 | 672 |
| 668 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 673 BrowserThread::PostTask( |
| 669 base::IgnoreReturn<bool>(base::Bind( | 674 BrowserThread::DB, FROM_HERE, |
| 670 &NativeBackendGnome::AddLogin, | 675 base::Bind(base::IgnoreResult(&NativeBackendGnome::AddLogin), |
| 671 base::Unretained(&backend), form_google_))); | 676 base::Unretained(&backend), form_google_)); |
| 672 | 677 |
| 673 RunBothThreads(); | 678 RunBothThreads(); |
| 674 } | 679 } |
| 675 | 680 |
| 676 EXPECT_EQ(1u, mock_keyring_items.size()); | 681 EXPECT_EQ(1u, mock_keyring_items.size()); |
| 677 if (mock_keyring_items.size() > 0) | 682 if (mock_keyring_items.size() > 0) |
| 678 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome"); | 683 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome"); |
| 679 | 684 |
| 680 // Now allow the migration. | 685 // Now allow the migration. |
| 681 mock_keyring_reject_local_ids = false; | 686 mock_keyring_reject_local_ids = false; |
| 682 | 687 |
| 683 { | 688 { |
| 684 NativeBackendGnome backend(42, profile_.GetPrefs()); | 689 NativeBackendGnome backend(42, profile_.GetPrefs()); |
| 685 backend.Init(); | 690 backend.Init(); |
| 686 | 691 |
| 687 // Trigger the migration by looking something up. | 692 // Trigger the migration by looking something up. |
| 688 std::vector<PasswordForm*> form_list; | 693 std::vector<PasswordForm*> form_list; |
| 689 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 694 BrowserThread::PostTask( |
| 690 base::IgnoreReturn<bool>(base::Bind( | 695 BrowserThread::DB, FROM_HERE, |
| 691 &NativeBackendGnome::GetAutofillableLogins, | 696 base::Bind( |
| 692 base::Unretained(&backend), &form_list))); | 697 base::IgnoreResult(&NativeBackendGnome::GetAutofillableLogins), |
| 698 base::Unretained(&backend), &form_list)); |
| 693 | 699 |
| 694 RunBothThreads(); | 700 RunBothThreads(); |
| 695 | 701 |
| 696 // Quick check that we got something back. | 702 // Quick check that we got something back. |
| 697 EXPECT_EQ(1u, form_list.size()); | 703 EXPECT_EQ(1u, form_list.size()); |
| 698 STLDeleteElements(&form_list); | 704 STLDeleteElements(&form_list); |
| 699 } | 705 } |
| 700 | 706 |
| 701 EXPECT_EQ(2u, mock_keyring_items.size()); | 707 EXPECT_EQ(2u, mock_keyring_items.size()); |
| 702 if (mock_keyring_items.size() > 0) | 708 if (mock_keyring_items.size() > 0) |
| 703 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome"); | 709 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome"); |
| 704 if (mock_keyring_items.size() > 1) | 710 if (mock_keyring_items.size() > 1) |
| 705 CheckMockKeyringItem(&mock_keyring_items[1], form_google_, "chrome-42"); | 711 CheckMockKeyringItem(&mock_keyring_items[1], form_google_, "chrome-42"); |
| 706 | 712 |
| 707 // Check that we have set the persistent preference. | 713 // Check that we have set the persistent preference. |
| 708 EXPECT_TRUE( | 714 EXPECT_TRUE( |
| 709 profile_.GetPrefs()->GetBoolean(prefs::kPasswordsUseLocalProfileId)); | 715 profile_.GetPrefs()->GetBoolean(prefs::kPasswordsUseLocalProfileId)); |
| 710 | 716 |
| 711 // Normally we'd actually have a different profile. But in the test just reset | 717 // Normally we'd actually have a different profile. But in the test just reset |
| 712 // the profile's persistent pref; we pass in the local profile id anyway. | 718 // the profile's persistent pref; we pass in the local profile id anyway. |
| 713 profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, false); | 719 profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, false); |
| 714 | 720 |
| 715 { | 721 { |
| 716 NativeBackendGnome backend(24, profile_.GetPrefs()); | 722 NativeBackendGnome backend(24, profile_.GetPrefs()); |
| 717 backend.Init(); | 723 backend.Init(); |
| 718 | 724 |
| 719 // Trigger the migration by looking something up. | 725 // Trigger the migration by looking something up. |
| 720 std::vector<PasswordForm*> form_list; | 726 std::vector<PasswordForm*> form_list; |
| 721 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 727 BrowserThread::PostTask( |
| 722 base::IgnoreReturn<bool>(base::Bind( | 728 BrowserThread::DB, FROM_HERE, |
| 723 &NativeBackendGnome::GetAutofillableLogins, | 729 base::Bind( |
| 724 base::Unretained(&backend), &form_list))); | 730 base::IgnoreResult(&NativeBackendGnome::GetAutofillableLogins), |
| 731 base::Unretained(&backend), &form_list)); |
| 725 | 732 |
| 726 RunBothThreads(); | 733 RunBothThreads(); |
| 727 | 734 |
| 728 // Quick check that we got something back. | 735 // Quick check that we got something back. |
| 729 EXPECT_EQ(1u, form_list.size()); | 736 EXPECT_EQ(1u, form_list.size()); |
| 730 STLDeleteElements(&form_list); | 737 STLDeleteElements(&form_list); |
| 731 } | 738 } |
| 732 | 739 |
| 733 EXPECT_EQ(3u, mock_keyring_items.size()); | 740 EXPECT_EQ(3u, mock_keyring_items.size()); |
| 734 if (mock_keyring_items.size() > 0) | 741 if (mock_keyring_items.size() > 0) |
| 735 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome"); | 742 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome"); |
| 736 if (mock_keyring_items.size() > 1) | 743 if (mock_keyring_items.size() > 1) |
| 737 CheckMockKeyringItem(&mock_keyring_items[1], form_google_, "chrome-42"); | 744 CheckMockKeyringItem(&mock_keyring_items[1], form_google_, "chrome-42"); |
| 738 if (mock_keyring_items.size() > 2) | 745 if (mock_keyring_items.size() > 2) |
| 739 CheckMockKeyringItem(&mock_keyring_items[2], form_google_, "chrome-24"); | 746 CheckMockKeyringItem(&mock_keyring_items[2], form_google_, "chrome-24"); |
| 740 } | 747 } |
| 741 | 748 |
| 742 TEST_F(NativeBackendGnomeTest, NoMigrationWithPrefSet) { | 749 TEST_F(NativeBackendGnomeTest, NoMigrationWithPrefSet) { |
| 743 // Reject attempts to migrate so we can populate the store. | 750 // Reject attempts to migrate so we can populate the store. |
| 744 mock_keyring_reject_local_ids = true; | 751 mock_keyring_reject_local_ids = true; |
| 745 | 752 |
| 746 { | 753 { |
| 747 NativeBackendGnome backend(42, profile_.GetPrefs()); | 754 NativeBackendGnome backend(42, profile_.GetPrefs()); |
| 748 backend.Init(); | 755 backend.Init(); |
| 749 | 756 |
| 750 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 757 BrowserThread::PostTask( |
| 751 base::IgnoreReturn<bool>(base::Bind( | 758 BrowserThread::DB, FROM_HERE, |
| 752 &NativeBackendGnome::AddLogin, | 759 base::Bind(base::IgnoreResult(&NativeBackendGnome::AddLogin), |
| 753 base::Unretained(&backend), form_google_))); | 760 base::Unretained(&backend), form_google_)); |
| 754 | 761 |
| 755 RunBothThreads(); | 762 RunBothThreads(); |
| 756 } | 763 } |
| 757 | 764 |
| 758 EXPECT_EQ(1u, mock_keyring_items.size()); | 765 EXPECT_EQ(1u, mock_keyring_items.size()); |
| 759 if (mock_keyring_items.size() > 0) | 766 if (mock_keyring_items.size() > 0) |
| 760 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome"); | 767 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome"); |
| 761 | 768 |
| 762 // Now allow migration, but also pretend that the it has already taken place. | 769 // Now allow migration, but also pretend that the it has already taken place. |
| 763 mock_keyring_reject_local_ids = false; | 770 mock_keyring_reject_local_ids = false; |
| 764 profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true); | 771 profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true); |
| 765 | 772 |
| 766 { | 773 { |
| 767 NativeBackendGnome backend(42, profile_.GetPrefs()); | 774 NativeBackendGnome backend(42, profile_.GetPrefs()); |
| 768 backend.Init(); | 775 backend.Init(); |
| 769 | 776 |
| 770 // Trigger the migration by adding a new login. | 777 // Trigger the migration by adding a new login. |
| 771 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 778 BrowserThread::PostTask( |
| 772 base::IgnoreReturn<bool>(base::Bind( | 779 BrowserThread::DB, FROM_HERE, |
| 773 &NativeBackendGnome::AddLogin, | 780 base::Bind(base::IgnoreResult(&NativeBackendGnome::AddLogin), |
| 774 base::Unretained(&backend), form_isc_))); | 781 base::Unretained(&backend), form_isc_)); |
| 775 | 782 |
| 776 // Look up all logins; we expect only the one we added. | 783 // Look up all logins; we expect only the one we added. |
| 777 std::vector<PasswordForm*> form_list; | 784 std::vector<PasswordForm*> form_list; |
| 778 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 785 BrowserThread::PostTask( |
| 779 base::IgnoreReturn<bool>(base::Bind( | 786 BrowserThread::DB, FROM_HERE, |
| 780 &NativeBackendGnome::GetAutofillableLogins, | 787 base::Bind( |
| 781 base::Unretained(&backend), &form_list))); | 788 base::IgnoreResult(&NativeBackendGnome::GetAutofillableLogins), |
| 789 base::Unretained(&backend), &form_list)); |
| 782 | 790 |
| 783 RunBothThreads(); | 791 RunBothThreads(); |
| 784 | 792 |
| 785 // Quick check that we got the right thing back. | 793 // Quick check that we got the right thing back. |
| 786 EXPECT_EQ(1u, form_list.size()); | 794 EXPECT_EQ(1u, form_list.size()); |
| 787 if (form_list.size() > 0) | 795 if (form_list.size() > 0) |
| 788 EXPECT_EQ(form_isc_.signon_realm, form_list[0]->signon_realm); | 796 EXPECT_EQ(form_isc_.signon_realm, form_list[0]->signon_realm); |
| 789 STLDeleteElements(&form_list); | 797 STLDeleteElements(&form_list); |
| 790 } | 798 } |
| 791 | 799 |
| 792 EXPECT_EQ(2u, mock_keyring_items.size()); | 800 EXPECT_EQ(2u, mock_keyring_items.size()); |
| 793 if (mock_keyring_items.size() > 0) | 801 if (mock_keyring_items.size() > 0) |
| 794 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome"); | 802 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome"); |
| 795 if (mock_keyring_items.size() > 1) | 803 if (mock_keyring_items.size() > 1) |
| 796 CheckMockKeyringItem(&mock_keyring_items[1], form_isc_, "chrome-42"); | 804 CheckMockKeyringItem(&mock_keyring_items[1], form_isc_, "chrome-42"); |
| 797 } | 805 } |
| 798 | 806 |
| 799 TEST_F(NativeBackendGnomeTest, DeleteMigratedPasswordIsIsolated) { | 807 TEST_F(NativeBackendGnomeTest, DeleteMigratedPasswordIsIsolated) { |
| 800 // Reject attempts to migrate so we can populate the store. | 808 // Reject attempts to migrate so we can populate the store. |
| 801 mock_keyring_reject_local_ids = true; | 809 mock_keyring_reject_local_ids = true; |
| 802 | 810 |
| 803 { | 811 { |
| 804 NativeBackendGnome backend(42, profile_.GetPrefs()); | 812 NativeBackendGnome backend(42, profile_.GetPrefs()); |
| 805 backend.Init(); | 813 backend.Init(); |
| 806 | 814 |
| 807 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 815 BrowserThread::PostTask( |
| 808 base::IgnoreReturn<bool>(base::Bind( | 816 BrowserThread::DB, FROM_HERE, |
| 809 &NativeBackendGnome::AddLogin, | 817 base::Bind(base::IgnoreResult(&NativeBackendGnome::AddLogin), |
| 810 base::Unretained(&backend), form_google_))); | 818 base::Unretained(&backend), form_google_)); |
| 811 | 819 |
| 812 RunBothThreads(); | 820 RunBothThreads(); |
| 813 } | 821 } |
| 814 | 822 |
| 815 EXPECT_EQ(1u, mock_keyring_items.size()); | 823 EXPECT_EQ(1u, mock_keyring_items.size()); |
| 816 if (mock_keyring_items.size() > 0) | 824 if (mock_keyring_items.size() > 0) |
| 817 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome"); | 825 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome"); |
| 818 | 826 |
| 819 // Now allow the migration. | 827 // Now allow the migration. |
| 820 mock_keyring_reject_local_ids = false; | 828 mock_keyring_reject_local_ids = false; |
| 821 | 829 |
| 822 { | 830 { |
| 823 NativeBackendGnome backend(42, profile_.GetPrefs()); | 831 NativeBackendGnome backend(42, profile_.GetPrefs()); |
| 824 backend.Init(); | 832 backend.Init(); |
| 825 | 833 |
| 826 // Trigger the migration by looking something up. | 834 // Trigger the migration by looking something up. |
| 827 std::vector<PasswordForm*> form_list; | 835 std::vector<PasswordForm*> form_list; |
| 828 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 836 BrowserThread::PostTask( |
| 829 base::IgnoreReturn<bool>(base::Bind( | 837 BrowserThread::DB, FROM_HERE, |
| 830 &NativeBackendGnome::GetAutofillableLogins, | 838 base::Bind( |
| 831 base::Unretained(&backend), &form_list))); | 839 base::IgnoreResult(&NativeBackendGnome::GetAutofillableLogins), |
| 840 base::Unretained(&backend), &form_list)); |
| 832 | 841 |
| 833 RunBothThreads(); | 842 RunBothThreads(); |
| 834 | 843 |
| 835 // Quick check that we got something back. | 844 // Quick check that we got something back. |
| 836 EXPECT_EQ(1u, form_list.size()); | 845 EXPECT_EQ(1u, form_list.size()); |
| 837 STLDeleteElements(&form_list); | 846 STLDeleteElements(&form_list); |
| 838 } | 847 } |
| 839 | 848 |
| 840 EXPECT_EQ(2u, mock_keyring_items.size()); | 849 EXPECT_EQ(2u, mock_keyring_items.size()); |
| 841 if (mock_keyring_items.size() > 0) | 850 if (mock_keyring_items.size() > 0) |
| 842 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome"); | 851 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome"); |
| 843 if (mock_keyring_items.size() > 1) | 852 if (mock_keyring_items.size() > 1) |
| 844 CheckMockKeyringItem(&mock_keyring_items[1], form_google_, "chrome-42"); | 853 CheckMockKeyringItem(&mock_keyring_items[1], form_google_, "chrome-42"); |
| 845 | 854 |
| 846 // Check that we have set the persistent preference. | 855 // Check that we have set the persistent preference. |
| 847 EXPECT_TRUE( | 856 EXPECT_TRUE( |
| 848 profile_.GetPrefs()->GetBoolean(prefs::kPasswordsUseLocalProfileId)); | 857 profile_.GetPrefs()->GetBoolean(prefs::kPasswordsUseLocalProfileId)); |
| 849 | 858 |
| 850 // Normally we'd actually have a different profile. But in the test just reset | 859 // Normally we'd actually have a different profile. But in the test just reset |
| 851 // the profile's persistent pref; we pass in the local profile id anyway. | 860 // the profile's persistent pref; we pass in the local profile id anyway. |
| 852 profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, false); | 861 profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, false); |
| 853 | 862 |
| 854 { | 863 { |
| 855 NativeBackendGnome backend(24, profile_.GetPrefs()); | 864 NativeBackendGnome backend(24, profile_.GetPrefs()); |
| 856 backend.Init(); | 865 backend.Init(); |
| 857 | 866 |
| 858 // Trigger the migration by looking something up. | 867 // Trigger the migration by looking something up. |
| 859 std::vector<PasswordForm*> form_list; | 868 std::vector<PasswordForm*> form_list; |
| 860 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 869 BrowserThread::PostTask( |
| 861 base::IgnoreReturn<bool>(base::Bind( | 870 BrowserThread::DB, FROM_HERE, |
| 862 &NativeBackendGnome::GetAutofillableLogins, | 871 base::Bind( |
| 863 base::Unretained(&backend), &form_list))); | 872 base::IgnoreResult(&NativeBackendGnome::GetAutofillableLogins), |
| 873 base::Unretained(&backend), &form_list)); |
| 864 | 874 |
| 865 RunBothThreads(); | 875 RunBothThreads(); |
| 866 | 876 |
| 867 // Quick check that we got something back. | 877 // Quick check that we got something back. |
| 868 EXPECT_EQ(1u, form_list.size()); | 878 EXPECT_EQ(1u, form_list.size()); |
| 869 STLDeleteElements(&form_list); | 879 STLDeleteElements(&form_list); |
| 870 | 880 |
| 871 // There should be three passwords now. | 881 // There should be three passwords now. |
| 872 EXPECT_EQ(3u, mock_keyring_items.size()); | 882 EXPECT_EQ(3u, mock_keyring_items.size()); |
| 873 if (mock_keyring_items.size() > 0) | 883 if (mock_keyring_items.size() > 0) |
| 874 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome"); | 884 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome"); |
| 875 if (mock_keyring_items.size() > 1) | 885 if (mock_keyring_items.size() > 1) |
| 876 CheckMockKeyringItem(&mock_keyring_items[1], form_google_, "chrome-42"); | 886 CheckMockKeyringItem(&mock_keyring_items[1], form_google_, "chrome-42"); |
| 877 if (mock_keyring_items.size() > 2) | 887 if (mock_keyring_items.size() > 2) |
| 878 CheckMockKeyringItem(&mock_keyring_items[2], form_google_, "chrome-24"); | 888 CheckMockKeyringItem(&mock_keyring_items[2], form_google_, "chrome-24"); |
| 879 | 889 |
| 880 // Now delete the password from this second profile. | 890 // Now delete the password from this second profile. |
| 881 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 891 BrowserThread::PostTask( |
| 882 base::IgnoreReturn<bool>(base::Bind( | 892 BrowserThread::DB, FROM_HERE, |
| 883 &NativeBackendGnome::RemoveLogin, | 893 base::Bind(base::IgnoreResult(&NativeBackendGnome::RemoveLogin), |
| 884 base::Unretained(&backend), form_google_))); | 894 base::Unretained(&backend), form_google_)); |
| 885 | 895 |
| 886 RunBothThreads(); | 896 RunBothThreads(); |
| 887 | 897 |
| 888 // The other two copies of the password in different profiles should remain. | 898 // The other two copies of the password in different profiles should remain. |
| 889 EXPECT_EQ(2u, mock_keyring_items.size()); | 899 EXPECT_EQ(2u, mock_keyring_items.size()); |
| 890 if (mock_keyring_items.size() > 0) | 900 if (mock_keyring_items.size() > 0) |
| 891 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome"); | 901 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome"); |
| 892 if (mock_keyring_items.size() > 1) | 902 if (mock_keyring_items.size() > 1) |
| 893 CheckMockKeyringItem(&mock_keyring_items[1], form_google_, "chrome-42"); | 903 CheckMockKeyringItem(&mock_keyring_items[1], form_google_, "chrome-42"); |
| 894 } | 904 } |
| 895 } | 905 } |
| OLD | NEW |