OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <algorithm> | 5 #include <algorithm> |
6 #include <map> | 6 #include <map> |
7 #include <set> | 7 #include <set> |
8 #include <string> | 8 #include <string> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 // legacy shared passwords in these tests, for testing the migration code. | 117 // legacy shared passwords in these tests, for testing the migration code. |
118 bool reject_local_folders_; | 118 bool reject_local_folders_; |
119 | 119 |
120 // No need to disallow copy and assign. This class is safe to copy and assign. | 120 // No need to disallow copy and assign. This class is safe to copy and assign. |
121 }; | 121 }; |
122 | 122 |
123 // Runs |backend->GetAutofillableLogins(forms)| and expects that the return | 123 // Runs |backend->GetAutofillableLogins(forms)| and expects that the return |
124 // value is false. | 124 // value is false. |
125 void CheckGetAutofillableLoginsFails( | 125 void CheckGetAutofillableLoginsFails( |
126 PasswordStoreX::NativeBackend* backend, | 126 PasswordStoreX::NativeBackend* backend, |
127 PasswordStoreX::NativeBackend::PasswordFormList* forms) { | 127 ScopedVector<autofill::PasswordForm>* forms) { |
128 EXPECT_FALSE(backend->GetAutofillableLogins(forms)); | 128 EXPECT_FALSE(backend->GetAutofillableLogins(forms)); |
129 } | 129 } |
130 | 130 |
131 } // anonymous namespace | 131 } // anonymous namespace |
132 | 132 |
133 // Obscure magic: we need to declare storage for this constant because we use it | 133 // Obscure magic: we need to declare storage for this constant because we use it |
134 // in ways that require its address in this test, but not in the actual code. | 134 // in ways that require its address in this test, but not in the actual code. |
135 const int NativeBackendKWallet::kInvalidKWalletHandle; | 135 const int NativeBackendKWallet::kInvalidKWalletHandle; |
136 | 136 |
137 // Subclass NativeBackendKWallet to promote some members to public for testing. | 137 // Subclass NativeBackendKWallet to promote some members to public for testing. |
(...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
592 EXPECT_TRUE(wallet_.hasFolder(folder)); | 592 EXPECT_TRUE(wallet_.hasFolder(folder)); |
593 std::vector<std::string> entries; | 593 std::vector<std::string> entries; |
594 EXPECT_TRUE(wallet_.entryList(folder, &entries)); | 594 EXPECT_TRUE(wallet_.entryList(folder, &entries)); |
595 EXPECT_EQ(sorted_expected.size(), entries.size()); | 595 EXPECT_EQ(sorted_expected.size(), entries.size()); |
596 std::sort(entries.begin(), entries.end()); | 596 std::sort(entries.begin(), entries.end()); |
597 for (size_t i = 0; i < entries.size() && i < sorted_expected.size(); ++i) { | 597 for (size_t i = 0; i < entries.size() && i < sorted_expected.size(); ++i) { |
598 EXPECT_EQ(sorted_expected[i].first, entries[i]); | 598 EXPECT_EQ(sorted_expected[i].first, entries[i]); |
599 TestKWallet::Blob value; | 599 TestKWallet::Blob value; |
600 EXPECT_TRUE(wallet_.readEntry(folder, entries[i], &value)); | 600 EXPECT_TRUE(wallet_.readEntry(folder, entries[i], &value)); |
601 Pickle pickle(reinterpret_cast<const char*>(value.data()), value.size()); | 601 Pickle pickle(reinterpret_cast<const char*>(value.data()), value.size()); |
602 std::vector<PasswordForm*> forms; | 602 ScopedVector<autofill::PasswordForm> forms; |
603 NativeBackendKWalletStub::DeserializeValue(entries[i], pickle, &forms); | 603 NativeBackendKWalletStub::DeserializeValue(entries[i], pickle, &forms); |
604 const std::vector<const PasswordForm*>& expect = sorted_expected[i].second; | 604 const std::vector<const PasswordForm*>& expect = sorted_expected[i].second; |
605 EXPECT_EQ(expect.size(), forms.size()); | 605 EXPECT_EQ(expect.size(), forms.size()); |
606 for (size_t j = 0; j < forms.size() && j < expect.size(); ++j) | 606 for (size_t j = 0; j < forms.size() && j < expect.size(); ++j) |
607 CheckPasswordForm(*expect[j], *forms[j]); | 607 CheckPasswordForm(*expect[j], *forms[j]); |
608 STLDeleteElements(&forms); | |
609 } | 608 } |
610 } | 609 } |
611 | 610 |
612 TEST_F(NativeBackendKWalletTest, NotEnabled) { | 611 TEST_F(NativeBackendKWalletTest, NotEnabled) { |
613 NativeBackendKWalletStub kwallet(42); | 612 NativeBackendKWalletStub kwallet(42); |
614 kwallet_enabled_ = false; | 613 kwallet_enabled_ = false; |
615 EXPECT_FALSE(kwallet.InitWithBus(mock_session_bus_)); | 614 EXPECT_FALSE(kwallet.InitWithBus(mock_session_bus_)); |
616 EXPECT_FALSE(klauncher_contacted_); | 615 EXPECT_FALSE(klauncher_contacted_); |
617 } | 616 } |
618 | 617 |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
703 | 702 |
704 TEST_F(NativeBackendKWalletTest, BasicListLogins) { | 703 TEST_F(NativeBackendKWalletTest, BasicListLogins) { |
705 NativeBackendKWalletStub backend(42); | 704 NativeBackendKWalletStub backend(42); |
706 EXPECT_TRUE(backend.InitWithBus(mock_session_bus_)); | 705 EXPECT_TRUE(backend.InitWithBus(mock_session_bus_)); |
707 | 706 |
708 BrowserThread::PostTask( | 707 BrowserThread::PostTask( |
709 BrowserThread::DB, FROM_HERE, | 708 BrowserThread::DB, FROM_HERE, |
710 base::Bind(base::IgnoreResult(&NativeBackendKWalletStub::AddLogin), | 709 base::Bind(base::IgnoreResult(&NativeBackendKWalletStub::AddLogin), |
711 base::Unretained(&backend), form_google_)); | 710 base::Unretained(&backend), form_google_)); |
712 | 711 |
713 std::vector<PasswordForm*> form_list; | 712 ScopedVector<autofill::PasswordForm> form_list; |
714 BrowserThread::PostTask( | 713 BrowserThread::PostTask( |
715 BrowserThread::DB, FROM_HERE, | 714 BrowserThread::DB, FROM_HERE, |
716 base::Bind( | 715 base::Bind( |
717 base::IgnoreResult(&NativeBackendKWalletStub::GetAutofillableLogins), | 716 base::IgnoreResult(&NativeBackendKWalletStub::GetAutofillableLogins), |
718 base::Unretained(&backend), &form_list)); | 717 base::Unretained(&backend), &form_list)); |
719 | 718 |
720 RunDBThread(); | 719 RunDBThread(); |
721 | 720 |
722 // Quick check that we got something back. | 721 // Quick check that we got something back. |
723 EXPECT_EQ(1u, form_list.size()); | 722 EXPECT_EQ(1u, form_list.size()); |
724 STLDeleteElements(&form_list); | |
725 | 723 |
726 EXPECT_FALSE(wallet_.hasFolder("Chrome Form Data")); | 724 EXPECT_FALSE(wallet_.hasFolder("Chrome Form Data")); |
727 | 725 |
728 std::vector<const PasswordForm*> forms; | 726 std::vector<const PasswordForm*> forms; |
729 forms.push_back(&form_google_); | 727 forms.push_back(&form_google_); |
730 ExpectationArray expected; | 728 ExpectationArray expected; |
731 expected.push_back(make_pair(std::string(form_google_.signon_realm), forms)); | 729 expected.push_back(make_pair(std::string(form_google_.signon_realm), forms)); |
732 CheckPasswordForms("Chrome Form Data (42)", expected); | 730 CheckPasswordForms("Chrome Form Data (42)", expected); |
733 } | 731 } |
734 | 732 |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
815 expected.push_back(make_pair(std::string(form_google_.signon_realm), forms)); | 813 expected.push_back(make_pair(std::string(form_google_.signon_realm), forms)); |
816 CheckPasswordForms("Chrome Form Data (42)", expected); | 814 CheckPasswordForms("Chrome Form Data (42)", expected); |
817 | 815 |
818 // Attempt to remove a login that doesn't exist. | 816 // Attempt to remove a login that doesn't exist. |
819 BrowserThread::PostTask( | 817 BrowserThread::PostTask( |
820 BrowserThread::DB, FROM_HERE, | 818 BrowserThread::DB, FROM_HERE, |
821 base::Bind(base::IgnoreResult(&NativeBackendKWalletStub::RemoveLogin), | 819 base::Bind(base::IgnoreResult(&NativeBackendKWalletStub::RemoveLogin), |
822 base::Unretained(&backend), form_isc_)); | 820 base::Unretained(&backend), form_isc_)); |
823 | 821 |
824 // Make sure we can still get the first form back. | 822 // Make sure we can still get the first form back. |
825 std::vector<PasswordForm*> form_list; | 823 ScopedVector<autofill::PasswordForm> form_list; |
826 BrowserThread::PostTask( | 824 BrowserThread::PostTask( |
827 BrowserThread::DB, FROM_HERE, | 825 BrowserThread::DB, FROM_HERE, |
828 base::Bind( | 826 base::Bind( |
829 base::IgnoreResult(&NativeBackendKWalletStub::GetAutofillableLogins), | 827 base::IgnoreResult(&NativeBackendKWalletStub::GetAutofillableLogins), |
830 base::Unretained(&backend), &form_list)); | 828 base::Unretained(&backend), &form_list)); |
831 | 829 |
832 RunDBThread(); | 830 RunDBThread(); |
833 | 831 |
834 // Quick check that we got something back. | 832 // Quick check that we got something back. |
835 EXPECT_EQ(1u, form_list.size()); | 833 EXPECT_EQ(1u, form_list.size()); |
836 STLDeleteElements(&form_list); | |
837 | 834 |
838 CheckPasswordForms("Chrome Form Data (42)", expected); | 835 CheckPasswordForms("Chrome Form Data (42)", expected); |
839 } | 836 } |
840 | 837 |
841 TEST_F(NativeBackendKWalletTest, AddDuplicateLogin) { | 838 TEST_F(NativeBackendKWalletTest, AddDuplicateLogin) { |
842 NativeBackendKWalletStub backend(42); | 839 NativeBackendKWalletStub backend(42); |
843 EXPECT_TRUE(backend.InitWithBus(mock_session_bus_)); | 840 EXPECT_TRUE(backend.InitWithBus(mock_session_bus_)); |
844 | 841 |
845 PasswordStoreChangeList changes; | 842 PasswordStoreChangeList changes; |
846 changes.push_back(PasswordStoreChange(PasswordStoreChange::ADD, | 843 changes.push_back(PasswordStoreChange(PasswordStoreChange::ADD, |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
880 TEST_F(NativeBackendKWalletTest, ListLoginsAppends) { | 877 TEST_F(NativeBackendKWalletTest, ListLoginsAppends) { |
881 NativeBackendKWalletStub backend(42); | 878 NativeBackendKWalletStub backend(42); |
882 EXPECT_TRUE(backend.InitWithBus(mock_session_bus_)); | 879 EXPECT_TRUE(backend.InitWithBus(mock_session_bus_)); |
883 | 880 |
884 BrowserThread::PostTask( | 881 BrowserThread::PostTask( |
885 BrowserThread::DB, FROM_HERE, | 882 BrowserThread::DB, FROM_HERE, |
886 base::Bind(base::IgnoreResult(&NativeBackendKWalletStub::AddLogin), | 883 base::Bind(base::IgnoreResult(&NativeBackendKWalletStub::AddLogin), |
887 base::Unretained(&backend), form_google_)); | 884 base::Unretained(&backend), form_google_)); |
888 | 885 |
889 // Send the same request twice with the same list both times. | 886 // Send the same request twice with the same list both times. |
890 std::vector<PasswordForm*> form_list; | 887 ScopedVector<autofill::PasswordForm> form_list; |
891 BrowserThread::PostTask( | 888 BrowserThread::PostTask( |
892 BrowserThread::DB, FROM_HERE, | 889 BrowserThread::DB, FROM_HERE, |
893 base::Bind( | 890 base::Bind( |
894 base::IgnoreResult(&NativeBackendKWalletStub::GetAutofillableLogins), | 891 base::IgnoreResult(&NativeBackendKWalletStub::GetAutofillableLogins), |
895 base::Unretained(&backend), &form_list)); | 892 base::Unretained(&backend), &form_list)); |
896 BrowserThread::PostTask( | 893 BrowserThread::PostTask( |
897 BrowserThread::DB, FROM_HERE, | 894 BrowserThread::DB, FROM_HERE, |
898 base::Bind( | 895 base::Bind( |
899 base::IgnoreResult(&NativeBackendKWalletStub::GetAutofillableLogins), | 896 base::IgnoreResult(&NativeBackendKWalletStub::GetAutofillableLogins), |
900 base::Unretained(&backend), &form_list)); | 897 base::Unretained(&backend), &form_list)); |
901 | 898 |
902 RunDBThread(); | 899 RunDBThread(); |
903 | 900 |
904 // Quick check that we got two results back. | 901 // Quick check that we got two results back. |
905 EXPECT_EQ(2u, form_list.size()); | 902 EXPECT_EQ(2u, form_list.size()); |
906 STLDeleteElements(&form_list); | |
907 | 903 |
908 EXPECT_FALSE(wallet_.hasFolder("Chrome Form Data")); | 904 EXPECT_FALSE(wallet_.hasFolder("Chrome Form Data")); |
909 | 905 |
910 std::vector<const PasswordForm*> forms; | 906 std::vector<const PasswordForm*> forms; |
911 forms.push_back(&form_google_); | 907 forms.push_back(&form_google_); |
912 ExpectationArray expected; | 908 ExpectationArray expected; |
913 expected.push_back(make_pair(std::string(form_google_.signon_realm), forms)); | 909 expected.push_back(make_pair(std::string(form_google_.signon_realm), forms)); |
914 CheckPasswordForms("Chrome Form Data (42)", expected); | 910 CheckPasswordForms("Chrome Form Data (42)", expected); |
915 } | 911 } |
916 | 912 |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
997 Pickle pickle; | 993 Pickle pickle; |
998 PasswordForm form = form_google_; | 994 PasswordForm form = form_google_; |
999 // Remove the fields which were not present in version #3. | 995 // Remove the fields which were not present in version #3. |
1000 form.display_name.clear(); | 996 form.display_name.clear(); |
1001 form.avatar_url = GURL(); | 997 form.avatar_url = GURL(); |
1002 form.federation_url = GURL(); | 998 form.federation_url = GURL(); |
1003 form.is_zero_click = false; | 999 form.is_zero_click = false; |
1004 CreateVersion3Pickle(form, &pickle); | 1000 CreateVersion3Pickle(form, &pickle); |
1005 | 1001 |
1006 ScopedVector<PasswordForm> form_list; | 1002 ScopedVector<PasswordForm> form_list; |
1007 NativeBackendKWalletStub::DeserializeValue(form.signon_realm, | 1003 NativeBackendKWalletStub::DeserializeValue(form.signon_realm, pickle, |
1008 pickle, &form_list.get()); | 1004 &form_list); |
1009 | 1005 |
1010 EXPECT_EQ(1u, form_list.size()); | 1006 EXPECT_EQ(1u, form_list.size()); |
1011 if (form_list.size() > 0) | 1007 if (form_list.size() > 0) |
1012 CheckPasswordForm(form, *form_list[0]); | 1008 CheckPasswordForm(form, *form_list[0]); |
1013 } | 1009 } |
1014 | 1010 |
1015 void NativeBackendKWalletPickleTest::CheckVersion2Pickle() { | 1011 void NativeBackendKWalletPickleTest::CheckVersion2Pickle() { |
1016 Pickle pickle; | 1012 Pickle pickle; |
1017 PasswordForm form = old_form_google_; | 1013 PasswordForm form = old_form_google_; |
1018 form.times_used = form_google_.times_used; | 1014 form.times_used = form_google_.times_used; |
1019 form.type = form_google_.type; | 1015 form.type = form_google_.type; |
1020 form.form_data = form_google_.form_data; | 1016 form.form_data = form_google_.form_data; |
1021 CreateVersion2Pickle(form, &pickle); | 1017 CreateVersion2Pickle(form, &pickle); |
1022 | 1018 |
1023 ScopedVector<PasswordForm> form_list; | 1019 ScopedVector<PasswordForm> form_list; |
1024 NativeBackendKWalletStub::DeserializeValue(form.signon_realm, | 1020 NativeBackendKWalletStub::DeserializeValue(form.signon_realm, pickle, |
1025 pickle, &form_list.get()); | 1021 &form_list); |
1026 | 1022 |
1027 EXPECT_EQ(1u, form_list.size()); | 1023 EXPECT_EQ(1u, form_list.size()); |
1028 if (form_list.size() > 0) | 1024 if (form_list.size() > 0) |
1029 CheckPasswordForm(form, *form_list[0]); | 1025 CheckPasswordForm(form, *form_list[0]); |
1030 } | 1026 } |
1031 | 1027 |
1032 // Make sure that we can still read version 1 pickles. | 1028 // Make sure that we can still read version 1 pickles. |
1033 void NativeBackendKWalletPickleTest::CheckVersion1Pickle() { | 1029 void NativeBackendKWalletPickleTest::CheckVersion1Pickle() { |
1034 Pickle pickle; | 1030 Pickle pickle; |
1035 PasswordForm form = form_google_; | 1031 PasswordForm form = form_google_; |
1036 CreateVersion1Pickle(form, &pickle); | 1032 CreateVersion1Pickle(form, &pickle); |
1037 | 1033 |
1038 std::vector<PasswordForm*> form_list; | 1034 ScopedVector<autofill::PasswordForm> form_list; |
1039 NativeBackendKWalletStub::DeserializeValue(form.signon_realm, | 1035 NativeBackendKWalletStub::DeserializeValue(form.signon_realm, |
1040 pickle, &form_list); | 1036 pickle, &form_list); |
1041 | 1037 |
1042 // This will match |old_form_google_| because not all the fields present in | 1038 // This will match |old_form_google_| because not all the fields present in |
1043 // |form_google_| will be deserialized. | 1039 // |form_google_| will be deserialized. |
1044 EXPECT_EQ(1u, form_list.size()); | 1040 EXPECT_EQ(1u, form_list.size()); |
1045 if (form_list.size() > 0) | 1041 if (form_list.size() > 0) |
1046 CheckPasswordForm(old_form_google_, *form_list[0]); | 1042 CheckPasswordForm(old_form_google_, *form_list[0]); |
1047 STLDeleteElements(&form_list); | |
1048 } | 1043 } |
1049 | 1044 |
1050 void NativeBackendKWalletPickleTest::CheckVersion0Pickle( | 1045 void NativeBackendKWalletPickleTest::CheckVersion0Pickle( |
1051 bool size_32, PasswordForm::Scheme scheme) { | 1046 bool size_32, PasswordForm::Scheme scheme) { |
1052 Pickle pickle; | 1047 Pickle pickle; |
1053 PasswordForm form = old_form_google_; | 1048 PasswordForm form = old_form_google_; |
1054 form.scheme = scheme; | 1049 form.scheme = scheme; |
1055 CreateVersion0Pickle(size_32, form, &pickle); | 1050 CreateVersion0Pickle(size_32, form, &pickle); |
1056 std::vector<PasswordForm*> form_list; | 1051 ScopedVector<autofill::PasswordForm> form_list; |
1057 NativeBackendKWalletStub::DeserializeValue(form.signon_realm, | 1052 NativeBackendKWalletStub::DeserializeValue(form.signon_realm, |
1058 pickle, &form_list); | 1053 pickle, &form_list); |
1059 EXPECT_EQ(1u, form_list.size()); | 1054 EXPECT_EQ(1u, form_list.size()); |
1060 if (form_list.size() > 0) | 1055 if (form_list.size() > 0) |
1061 CheckPasswordForm(form, *form_list[0]); | 1056 CheckPasswordForm(form, *form_list[0]); |
1062 STLDeleteElements(&form_list); | |
1063 } | 1057 } |
1064 | 1058 |
1065 // Check that if KWallet fails to respond, the backend propagates the error. | 1059 // Check that if KWallet fails to respond, the backend propagates the error. |
1066 TEST_F(NativeBackendKWalletTest, GetAllLoginsErrorHandling) { | 1060 TEST_F(NativeBackendKWalletTest, GetAllLoginsErrorHandling) { |
1067 NativeBackendKWalletStub backend(42); | 1061 NativeBackendKWalletStub backend(42); |
1068 EXPECT_TRUE(backend.InitWithBus(mock_session_bus_)); | 1062 EXPECT_TRUE(backend.InitWithBus(mock_session_bus_)); |
1069 // Make KWallet fail on calling readEntry. | 1063 // Make KWallet fail on calling readEntry. |
1070 failing_methods_.insert("readEntry"); | 1064 failing_methods_.insert("readEntry"); |
1071 | 1065 |
1072 // Store some non-blacklisted logins to be potentially returned. | 1066 // Store some non-blacklisted logins to be potentially returned. |
1073 BrowserThread::PostTask( | 1067 BrowserThread::PostTask( |
1074 BrowserThread::DB, FROM_HERE, | 1068 BrowserThread::DB, FROM_HERE, |
1075 base::Bind(base::IgnoreResult(&NativeBackendKWalletStub::AddLogin), | 1069 base::Bind(base::IgnoreResult(&NativeBackendKWalletStub::AddLogin), |
1076 base::Unretained(&backend), form_google_)); | 1070 base::Unretained(&backend), form_google_)); |
1077 | 1071 |
1078 // Verify that nothing is in fact returned, because KWallet fails to respond. | 1072 // Verify that nothing is in fact returned, because KWallet fails to respond. |
1079 std::vector<PasswordForm*> form_list; | 1073 ScopedVector<autofill::PasswordForm> form_list; |
1080 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 1074 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, |
1081 base::Bind(&CheckGetAutofillableLoginsFails, | 1075 base::Bind(&CheckGetAutofillableLoginsFails, |
1082 base::Unretained(&backend), &form_list)); | 1076 base::Unretained(&backend), &form_list)); |
1083 RunDBThread(); | 1077 RunDBThread(); |
1084 EXPECT_EQ(0u, form_list.size()); | 1078 EXPECT_EQ(0u, form_list.size()); |
1085 } | 1079 } |
1086 | 1080 |
1087 // We try both SCHEME_HTML and SCHEME_BASIC since the scheme is stored right | 1081 // We try both SCHEME_HTML and SCHEME_BASIC since the scheme is stored right |
1088 // after the size in the pickle, so it's what gets read as part of the count | 1082 // after the size in the pickle, so it's what gets read as part of the count |
1089 // when reading 32-bit pickles on 64-bit systems. SCHEME_HTML is 0 (so we'll | 1083 // when reading 32-bit pickles on 64-bit systems. SCHEME_HTML is 0 (so we'll |
(...skipping 22 matching lines...) Expand all Loading... |
1112 CheckVersion1Pickle(); | 1106 CheckVersion1Pickle(); |
1113 } | 1107 } |
1114 | 1108 |
1115 TEST_F(NativeBackendKWalletPickleTest, CheckVersion2Pickle) { | 1109 TEST_F(NativeBackendKWalletPickleTest, CheckVersion2Pickle) { |
1116 CheckVersion2Pickle(); | 1110 CheckVersion2Pickle(); |
1117 } | 1111 } |
1118 | 1112 |
1119 TEST_F(NativeBackendKWalletPickleTest, CheckVersion3Pickle) { | 1113 TEST_F(NativeBackendKWalletPickleTest, CheckVersion3Pickle) { |
1120 CheckVersion3Pickle(); | 1114 CheckVersion3Pickle(); |
1121 } | 1115 } |
OLD | NEW |