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
3 // found in the LICENSE file.
11 #include "base/bind.h"
12 #include "base/location.h"
13 #include "base/pickle.h"
14 #include "base/prefs/pref_service.h"
15 #include "base/single_thread_task_runner.h"
16 #include "base/stl_util.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "base/synchronization/waitable_event.h"
19 #include "base/thread_task_runner_handle.h"
20 #include "chrome/browser/password_manager/native_backend_kwallet_x.h"
21 #include "chrome/test/base/testing_profile.h"
22 #include "components/autofill/core/common/password_form.h"
23 #include "components/password_manager/core/common/password_manager_pref_names.h"
24 #include "content/public/test/test_browser_thread.h"
25 #include "dbus/message.h"
26 #include "dbus/mock_bus.h"
27 #include "dbus/mock_object_proxy.h"
28 #include "dbus/object_path.h"
29 #include "dbus/object_proxy.h"
30 #include "testing/gmock/include/gmock/gmock.h"
31 #include "testing/gtest/include/gtest/gtest.h"
33 using autofill::PasswordForm
;
34 using base::UTF8ToUTF16
;
35 using content::BrowserThread
;
36 using password_manager::PasswordStoreChange
;
37 using password_manager::PasswordStoreChangeList
;
39 using testing::Invoke
;
40 using testing::Return
;
44 // This class implements a very simple version of KWallet in memory.
45 // We only provide the parts we actually use; the real version has more.
48 typedef std::basic_string
<uint8_t> Blob
; // std::string is binary-safe.
50 TestKWallet() : reject_local_folders_(false) {}
52 void set_reject_local_folders(bool value
) { reject_local_folders_
= value
; }
54 // NOTE: The method names here are the same as the corresponding DBus
55 // methods, and therefore have names that don't match our style guide.
57 // Check for presence of a given password folder.
58 bool hasFolder(const std::string
& folder
) const {
59 return data_
.find(folder
) != data_
.end();
62 // Check for presence of a given password in a given password folder.
63 bool hasEntry(const std::string
& folder
, const std::string
& key
) const {
64 Data::const_iterator it
= data_
.find(folder
);
65 return it
!= data_
.end() && it
->second
.find(key
) != it
->second
.end();
68 // Get a list of password keys in a given password folder.
69 bool entryList(const std::string
& folder
,
70 std::vector
<std::string
>* entries
) const {
71 Data::const_iterator it
= data_
.find(folder
);
72 if (it
== data_
.end()) return false;
73 for (Folder::const_iterator fit
= it
->second
.begin();
74 fit
!= it
->second
.end(); ++fit
)
75 entries
->push_back(fit
->first
);
79 // Read the password data for a given password in a given password folder.
80 bool readEntry(const std::string
& folder
, const std::string
& key
,
82 Data::const_iterator it
= data_
.find(folder
);
83 if (it
== data_
.end()) return false;
84 Folder::const_iterator fit
= it
->second
.find(key
);
85 if (fit
== it
->second
.end()) return false;
90 // Create the given password folder.
91 bool createFolder(const std::string
& folder
) {
92 if (reject_local_folders_
&& folder
.find('(') != std::string::npos
)
94 return data_
.insert(make_pair(folder
, Folder())).second
;
97 // Remove the given password from the given password folder.
98 bool removeEntry(const std::string
& folder
, const std::string
& key
) {
99 Data::iterator it
= data_
.find(folder
);
100 if (it
== data_
.end()) return false;
101 return it
->second
.erase(key
) > 0;
104 // Write the given password data to the given password folder.
105 bool writeEntry(const std::string
& folder
, const std::string
& key
,
107 Data::iterator it
= data_
.find(folder
);
108 if (it
== data_
.end()) return false;
109 it
->second
[key
] = value
;
114 typedef std::map
<std::string
, Blob
> Folder
;
115 typedef std::map
<std::string
, Folder
> Data
;
118 // "Local" folders are folders containing local profile IDs in their names. We
119 // can reject attempts to create them in order to make it easier to create
120 // legacy shared passwords in these tests, for testing the migration code.
121 bool reject_local_folders_
;
123 // No need to disallow copy and assign. This class is safe to copy and assign.
126 // Runs |backend->GetAutofillableLogins(forms)| and expects that the return
128 void CheckGetAutofillableLoginsFails(
129 PasswordStoreX::NativeBackend
* backend
,
130 ScopedVector
<autofill::PasswordForm
>* forms
) {
131 EXPECT_FALSE(backend
->GetAutofillableLogins(forms
));
134 } // anonymous namespace
136 // Obscure magic: we need to declare storage for this constant because we use it
137 // in ways that require its address in this test, but not in the actual code.
138 const int NativeBackendKWallet::kInvalidKWalletHandle
;
140 // Subclass NativeBackendKWallet to promote some members to public for testing.
141 class NativeBackendKWalletStub
: public NativeBackendKWallet
{
143 explicit NativeBackendKWalletStub(LocalProfileId id
)
144 : NativeBackendKWallet(id
) {
146 using NativeBackendKWallet::InitWithBus
;
147 using NativeBackendKWallet::kInvalidKWalletHandle
;
148 using NativeBackendKWallet::DeserializeValue
;
151 // Provide some test forms to avoid having to set them up in each test.
152 class NativeBackendKWalletTestBase
: public testing::Test
{
154 NativeBackendKWalletTestBase() {
155 old_form_google_
.origin
= GURL("http://www.google.com/");
156 old_form_google_
.action
= GURL("http://www.google.com/login");
157 old_form_google_
.username_element
= UTF8ToUTF16("user");
158 old_form_google_
.username_value
= UTF8ToUTF16("joeschmoe");
159 old_form_google_
.password_element
= UTF8ToUTF16("pass");
160 old_form_google_
.password_value
= UTF8ToUTF16("seekrit");
161 old_form_google_
.submit_element
= UTF8ToUTF16("submit");
162 old_form_google_
.signon_realm
= "Google";
163 old_form_google_
.date_created
= base::Time::Now();
165 form_google_
= old_form_google_
;
166 form_google_
.times_used
= 3;
167 form_google_
.type
= PasswordForm::TYPE_GENERATED
;
168 form_google_
.form_data
.name
= UTF8ToUTF16("form_name");
169 form_google_
.date_synced
= base::Time::Now();
170 form_google_
.date_created
= old_form_google_
.date_created
;
171 form_google_
.display_name
= UTF8ToUTF16("Joe Schmoe");
172 form_google_
.icon_url
= GURL("http://www.google.com/icon");
173 form_google_
.federation_url
= GURL("http://www.google.com/federation_url");
174 form_google_
.skip_zero_click
= true;
175 form_google_
.generation_upload_status
= PasswordForm::NEGATIVE_SIGNAL_SENT
;
177 form_isc_
.origin
= GURL("http://www.isc.org/");
178 form_isc_
.action
= GURL("http://www.isc.org/auth");
179 form_isc_
.username_element
= UTF8ToUTF16("id");
180 form_isc_
.username_value
= UTF8ToUTF16("janedoe");
181 form_isc_
.password_element
= UTF8ToUTF16("passwd");
182 form_isc_
.password_value
= UTF8ToUTF16("ihazabukkit");
183 form_isc_
.submit_element
= UTF8ToUTF16("login");
184 form_isc_
.signon_realm
= "ISC";
185 form_isc_
.date_synced
= base::Time::Now();
186 form_isc_
.date_created
= base::Time::Now();
189 static void CheckPasswordForm(const PasswordForm
& expected
,
190 const PasswordForm
& actual
,
191 bool check_date_created
);
192 static void CheckPasswordChanges(const PasswordStoreChangeList
& expected
,
193 const PasswordStoreChangeList
& actual
);
194 static void CheckPasswordChangesWithResult(
195 const PasswordStoreChangeList
* expected
,
196 const PasswordStoreChangeList
* actual
,
199 PasswordForm old_form_google_
;
200 PasswordForm form_google_
;
201 PasswordForm form_isc_
;
205 void NativeBackendKWalletTestBase::CheckPasswordForm(
206 const PasswordForm
& expected
,
207 const PasswordForm
& actual
,
208 bool check_date_created
) {
209 EXPECT_EQ(expected
.origin
, actual
.origin
);
210 EXPECT_EQ(expected
.password_value
, actual
.password_value
);
211 EXPECT_EQ(expected
.action
, actual
.action
);
212 EXPECT_EQ(expected
.username_element
, actual
.username_element
);
213 EXPECT_EQ(expected
.username_value
, actual
.username_value
);
214 EXPECT_EQ(expected
.password_element
, actual
.password_element
);
215 EXPECT_EQ(expected
.submit_element
, actual
.submit_element
);
216 EXPECT_EQ(expected
.signon_realm
, actual
.signon_realm
);
217 EXPECT_EQ(expected
.ssl_valid
, actual
.ssl_valid
);
218 EXPECT_EQ(expected
.preferred
, actual
.preferred
);
219 if (check_date_created
) {
220 EXPECT_EQ(expected
.date_created
, actual
.date_created
);
222 EXPECT_EQ(expected
.blacklisted_by_user
, actual
.blacklisted_by_user
);
223 EXPECT_EQ(expected
.type
, actual
.type
);
224 EXPECT_EQ(expected
.times_used
, actual
.times_used
);
225 EXPECT_EQ(expected
.scheme
, actual
.scheme
);
226 EXPECT_EQ(expected
.date_synced
, actual
.date_synced
);
227 EXPECT_EQ(expected
.display_name
, actual
.display_name
);
228 EXPECT_EQ(expected
.icon_url
, actual
.icon_url
);
229 EXPECT_EQ(expected
.federation_url
, actual
.federation_url
);
230 EXPECT_EQ(expected
.skip_zero_click
, actual
.skip_zero_click
);
231 EXPECT_EQ(expected
.generation_upload_status
, actual
.generation_upload_status
);
235 void NativeBackendKWalletTestBase::CheckPasswordChanges(
236 const PasswordStoreChangeList
& expected
,
237 const PasswordStoreChangeList
& actual
) {
238 ASSERT_EQ(expected
.size(), actual
.size());
239 for (size_t i
= 0; i
< expected
.size(); ++i
) {
240 EXPECT_EQ(expected
[i
].type(), actual
[i
].type());
241 CheckPasswordForm(expected
[i
].form(), actual
[i
].form(), true);
246 void NativeBackendKWalletTestBase::CheckPasswordChangesWithResult(
247 const PasswordStoreChangeList
* expected
,
248 const PasswordStoreChangeList
* actual
,
251 CheckPasswordChanges(*expected
, *actual
);
254 class NativeBackendKWalletTest
: public NativeBackendKWalletTestBase
{
256 NativeBackendKWalletTest()
257 : ui_thread_(BrowserThread::UI
, &message_loop_
),
258 db_thread_(BrowserThread::DB
), klauncher_ret_(0),
259 klauncher_contacted_(false), kwallet_runnable_(true),
260 kwallet_running_(true), kwallet_enabled_(true) {
263 void SetUp() override
;
264 void TearDown() override
;
266 // Let the DB thread run to completion of all current tasks.
268 base::WaitableEvent
event(false, false);
269 BrowserThread::PostTask(BrowserThread::DB
, FROM_HERE
,
270 base::Bind(ThreadDone
, &event
));
272 // Some of the tests may post messages to the UI thread, but we don't need
273 // to run those until after the DB thread is finished. So run it here.
274 message_loop_
.RunUntilIdle();
276 static void ThreadDone(base::WaitableEvent
* event
) {
280 // Utilities to help verify sets of expectations.
282 std::pair
<std::string
,
283 std::vector
<const PasswordForm
*> > > ExpectationArray
;
284 void CheckPasswordForms(const std::string
& folder
,
285 const ExpectationArray
& sorted_expected
);
287 enum RemoveBetweenMethod
{
292 // Tests RemoveLoginsCreatedBetween or RemoveLoginsSyncedBetween.
293 void TestRemoveLoginsBetween(RemoveBetweenMethod date_to_test
);
295 base::MessageLoopForUI message_loop_
;
296 content::TestBrowserThread ui_thread_
;
297 content::TestBrowserThread db_thread_
;
299 scoped_refptr
<dbus::MockBus
> mock_session_bus_
;
300 scoped_refptr
<dbus::MockObjectProxy
> mock_klauncher_proxy_
;
301 scoped_refptr
<dbus::MockObjectProxy
> mock_kwallet_proxy_
;
304 std::string klauncher_error_
;
305 bool klauncher_contacted_
;
307 bool kwallet_runnable_
;
308 bool kwallet_running_
;
309 bool kwallet_enabled_
;
313 // For all method names contained in |failing_methods_|, the mocked KWallet
314 // will return a null response.
315 std::set
<std::string
> failing_methods_
;
318 dbus::Response
* KLauncherMethodCall(
319 dbus::MethodCall
* method_call
, testing::Unused
);
321 dbus::Response
* KWalletMethodCall(
322 dbus::MethodCall
* method_call
, testing::Unused
);
325 void NativeBackendKWalletTest::SetUp() {
326 ASSERT_TRUE(db_thread_
.Start());
328 dbus::Bus::Options options
;
329 options
.bus_type
= dbus::Bus::SESSION
;
330 mock_session_bus_
= new dbus::MockBus(options
);
332 mock_klauncher_proxy_
=
333 new dbus::MockObjectProxy(mock_session_bus_
.get(),
335 dbus::ObjectPath("/KLauncher"));
336 EXPECT_CALL(*mock_klauncher_proxy_
.get(), MockCallMethodAndBlock(_
, _
))
338 Invoke(this, &NativeBackendKWalletTest::KLauncherMethodCall
));
340 mock_kwallet_proxy_
=
341 new dbus::MockObjectProxy(mock_session_bus_
.get(),
343 dbus::ObjectPath("/modules/kwalletd"));
344 EXPECT_CALL(*mock_kwallet_proxy_
.get(), MockCallMethodAndBlock(_
, _
))
346 Invoke(this, &NativeBackendKWalletTest::KWalletMethodCall
));
349 *mock_session_bus_
.get(),
350 GetObjectProxy("org.kde.klauncher", dbus::ObjectPath("/KLauncher")))
351 .WillRepeatedly(Return(mock_klauncher_proxy_
.get()));
353 *mock_session_bus_
.get(),
354 GetObjectProxy("org.kde.kwalletd", dbus::ObjectPath("/modules/kwalletd")))
355 .WillRepeatedly(Return(mock_kwallet_proxy_
.get()));
357 EXPECT_CALL(*mock_session_bus_
.get(), ShutdownAndBlock()).WillOnce(Return())
358 .WillRepeatedly(Return());
361 void NativeBackendKWalletTest::TearDown() {
362 base::ThreadTaskRunnerHandle::Get()->PostTask(
363 FROM_HERE
, base::MessageLoop::QuitClosure());
364 base::MessageLoop::current()->Run();
368 void NativeBackendKWalletTest::TestRemoveLoginsBetween(
369 RemoveBetweenMethod date_to_test
) {
370 NativeBackendKWalletStub
backend(42);
371 EXPECT_TRUE(backend
.InitWithBus(mock_session_bus_
));
373 form_google_
.date_synced
= base::Time();
374 form_isc_
.date_synced
= base::Time();
375 form_google_
.date_created
= base::Time();
376 form_isc_
.date_created
= base::Time();
377 base::Time now
= base::Time::Now();
378 base::Time next_day
= now
+ base::TimeDelta::FromDays(1);
379 if (date_to_test
== CREATED
) {
380 form_google_
.date_created
= now
;
381 form_isc_
.date_created
= next_day
;
383 form_google_
.date_synced
= now
;
384 form_isc_
.date_synced
= next_day
;
387 BrowserThread::PostTask(
390 base::Bind(base::IgnoreResult(&NativeBackendKWalletStub::AddLogin
),
391 base::Unretained(&backend
),
393 BrowserThread::PostTask(
396 base::Bind(base::IgnoreResult(&NativeBackendKWalletStub::AddLogin
),
397 base::Unretained(&backend
),
400 PasswordStoreChangeList expected_changes
;
401 expected_changes
.push_back(
402 PasswordStoreChange(PasswordStoreChange::REMOVE
, form_google_
));
403 PasswordStoreChangeList changes
;
404 bool (NativeBackendKWallet::*method
)(
405 base::Time
, base::Time
, password_manager::PasswordStoreChangeList
*) =
406 date_to_test
== CREATED
407 ? &NativeBackendKWalletStub::RemoveLoginsCreatedBetween
408 : &NativeBackendKWalletStub::RemoveLoginsSyncedBetween
;
409 BrowserThread::PostTaskAndReplyWithResult(
413 method
, base::Unretained(&backend
), base::Time(), next_day
, &changes
),
414 base::Bind(&NativeBackendKWalletTest::CheckPasswordChangesWithResult
,
419 std::vector
<const PasswordForm
*> forms
;
420 forms
.push_back(&form_isc_
);
421 ExpectationArray expected
;
422 expected
.push_back(make_pair(std::string(form_isc_
.signon_realm
), forms
));
423 CheckPasswordForms("Chrome Form Data (42)", expected
);
426 expected_changes
.clear();
427 expected_changes
.push_back(
428 PasswordStoreChange(PasswordStoreChange::REMOVE
, form_isc_
));
429 BrowserThread::PostTaskAndReplyWithResult(
433 method
, base::Unretained(&backend
), next_day
, base::Time(), &changes
),
434 base::Bind(&NativeBackendKWalletTest::CheckPasswordChangesWithResult
,
439 CheckPasswordForms("Chrome Form Data (42)", ExpectationArray());
442 dbus::Response
* NativeBackendKWalletTest::KLauncherMethodCall(
443 dbus::MethodCall
* method_call
, testing::Unused
) {
444 EXPECT_EQ("org.kde.KLauncher", method_call
->GetInterface());
445 EXPECT_EQ("start_service_by_desktop_name", method_call
->GetMember());
447 klauncher_contacted_
= true;
449 dbus::MessageReader
reader(method_call
);
450 std::string service_name
;
451 std::vector
<std::string
> urls
;
452 std::vector
<std::string
> envs
;
453 std::string startup_id
;
456 EXPECT_TRUE(reader
.PopString(&service_name
));
457 EXPECT_TRUE(reader
.PopArrayOfStrings(&urls
));
458 EXPECT_TRUE(reader
.PopArrayOfStrings(&envs
));
459 EXPECT_TRUE(reader
.PopString(&startup_id
));
460 EXPECT_TRUE(reader
.PopBool(&blind
));
462 EXPECT_EQ("kwalletd", service_name
);
463 EXPECT_TRUE(urls
.empty());
464 EXPECT_TRUE(envs
.empty());
465 EXPECT_TRUE(startup_id
.empty());
468 if (kwallet_runnable_
)
469 kwallet_running_
= true;
471 scoped_ptr
<dbus::Response
> response(dbus::Response::CreateEmpty());
472 dbus::MessageWriter
writer(response
.get());
473 writer
.AppendInt32(klauncher_ret_
);
474 writer
.AppendString(std::string()); // dbus_name
475 writer
.AppendString(klauncher_error_
);
476 writer
.AppendInt32(1234); // pid
477 return response
.release();
480 dbus::Response
* NativeBackendKWalletTest::KWalletMethodCall(
481 dbus::MethodCall
* method_call
, testing::Unused
) {
482 if (!kwallet_running_
)
484 EXPECT_EQ("org.kde.KWallet", method_call
->GetInterface());
486 if (ContainsKey(failing_methods_
, method_call
->GetMember()))
488 scoped_ptr
<dbus::Response
> response
;
489 if (method_call
->GetMember() == "isEnabled") {
490 response
= dbus::Response::CreateEmpty();
491 dbus::MessageWriter
writer(response
.get());
492 writer
.AppendBool(kwallet_enabled_
);
493 } else if (method_call
->GetMember() == "networkWallet") {
494 response
= dbus::Response::CreateEmpty();
495 dbus::MessageWriter
writer(response
.get());
496 writer
.AppendString("test_wallet"); // Should match |open| below.
497 } else if (method_call
->GetMember() == "open") {
498 dbus::MessageReader
reader(method_call
);
499 std::string wallet_name
;
501 std::string app_name
;
502 EXPECT_TRUE(reader
.PopString(&wallet_name
));
503 EXPECT_TRUE(reader
.PopInt64(&wallet_id
));
504 EXPECT_TRUE(reader
.PopString(&app_name
));
505 EXPECT_EQ("test_wallet", wallet_name
); // Should match |networkWallet|.
506 response
= dbus::Response::CreateEmpty();
507 dbus::MessageWriter
writer(response
.get());
508 writer
.AppendInt32(1); // Can be anything but kInvalidKWalletHandle.
509 } else if (method_call
->GetMember() == "hasFolder" ||
510 method_call
->GetMember() == "createFolder") {
511 dbus::MessageReader
reader(method_call
);
512 int handle
= NativeBackendKWalletStub::kInvalidKWalletHandle
;
513 std::string folder_name
;
514 std::string app_name
;
515 EXPECT_TRUE(reader
.PopInt32(&handle
));
516 EXPECT_TRUE(reader
.PopString(&folder_name
));
517 EXPECT_TRUE(reader
.PopString(&app_name
));
518 EXPECT_NE(NativeBackendKWalletStub::kInvalidKWalletHandle
, handle
);
519 response
= dbus::Response::CreateEmpty();
520 dbus::MessageWriter
writer(response
.get());
521 if (method_call
->GetMember() == "hasFolder")
522 writer
.AppendBool(wallet_
.hasFolder(folder_name
));
524 writer
.AppendBool(wallet_
.createFolder(folder_name
));
525 } else if (method_call
->GetMember() == "hasEntry" ||
526 method_call
->GetMember() == "removeEntry") {
527 dbus::MessageReader
reader(method_call
);
528 int handle
= NativeBackendKWalletStub::kInvalidKWalletHandle
;
529 std::string folder_name
;
531 std::string app_name
;
532 EXPECT_TRUE(reader
.PopInt32(&handle
));
533 EXPECT_TRUE(reader
.PopString(&folder_name
));
534 EXPECT_TRUE(reader
.PopString(&key
));
535 EXPECT_TRUE(reader
.PopString(&app_name
));
536 EXPECT_NE(NativeBackendKWalletStub::kInvalidKWalletHandle
, handle
);
537 response
= dbus::Response::CreateEmpty();
538 dbus::MessageWriter
writer(response
.get());
539 if (method_call
->GetMember() == "hasEntry")
540 writer
.AppendBool(wallet_
.hasEntry(folder_name
, key
));
542 writer
.AppendInt32(wallet_
.removeEntry(folder_name
, key
) ? 0 : 1);
543 } else if (method_call
->GetMember() == "entryList") {
544 dbus::MessageReader
reader(method_call
);
545 int handle
= NativeBackendKWalletStub::kInvalidKWalletHandle
;
546 std::string folder_name
;
547 std::string app_name
;
548 EXPECT_TRUE(reader
.PopInt32(&handle
));
549 EXPECT_TRUE(reader
.PopString(&folder_name
));
550 EXPECT_TRUE(reader
.PopString(&app_name
));
551 EXPECT_NE(NativeBackendKWalletStub::kInvalidKWalletHandle
, handle
);
552 std::vector
<std::string
> entries
;
553 if (wallet_
.entryList(folder_name
, &entries
)) {
554 response
= dbus::Response::CreateEmpty();
555 dbus::MessageWriter
writer(response
.get());
556 writer
.AppendArrayOfStrings(entries
);
558 } else if (method_call
->GetMember() == "readEntry") {
559 dbus::MessageReader
reader(method_call
);
560 int handle
= NativeBackendKWalletStub::kInvalidKWalletHandle
;
561 std::string folder_name
;
563 std::string app_name
;
564 EXPECT_TRUE(reader
.PopInt32(&handle
));
565 EXPECT_TRUE(reader
.PopString(&folder_name
));
566 EXPECT_TRUE(reader
.PopString(&key
));
567 EXPECT_TRUE(reader
.PopString(&app_name
));
568 EXPECT_NE(NativeBackendKWalletStub::kInvalidKWalletHandle
, handle
);
569 TestKWallet::Blob value
;
570 if (wallet_
.readEntry(folder_name
, key
, &value
)) {
571 response
= dbus::Response::CreateEmpty();
572 dbus::MessageWriter
writer(response
.get());
573 writer
.AppendArrayOfBytes(value
.data(), value
.size());
575 } else if (method_call
->GetMember() == "writeEntry") {
576 dbus::MessageReader
reader(method_call
);
577 int handle
= NativeBackendKWalletStub::kInvalidKWalletHandle
;
578 std::string folder_name
;
580 const uint8_t* bytes
= nullptr;
582 std::string app_name
;
583 EXPECT_TRUE(reader
.PopInt32(&handle
));
584 EXPECT_TRUE(reader
.PopString(&folder_name
));
585 EXPECT_TRUE(reader
.PopString(&key
));
586 EXPECT_TRUE(reader
.PopArrayOfBytes(&bytes
, &length
));
587 EXPECT_TRUE(reader
.PopString(&app_name
));
588 EXPECT_NE(NativeBackendKWalletStub::kInvalidKWalletHandle
, handle
);
589 response
= dbus::Response::CreateEmpty();
590 dbus::MessageWriter
writer(response
.get());
592 wallet_
.writeEntry(folder_name
, key
,
593 TestKWallet::Blob(bytes
, length
)) ? 0 : 1);
596 EXPECT_TRUE(response
);
597 return response
.release();
600 void NativeBackendKWalletTest::CheckPasswordForms(
601 const std::string
& folder
, const ExpectationArray
& sorted_expected
) {
602 EXPECT_TRUE(wallet_
.hasFolder(folder
));
603 std::vector
<std::string
> entries
;
604 EXPECT_TRUE(wallet_
.entryList(folder
, &entries
));
605 EXPECT_EQ(sorted_expected
.size(), entries
.size());
606 std::sort(entries
.begin(), entries
.end());
607 for (size_t i
= 0; i
< entries
.size() && i
< sorted_expected
.size(); ++i
) {
608 EXPECT_EQ(sorted_expected
[i
].first
, entries
[i
]);
609 TestKWallet::Blob value
;
610 EXPECT_TRUE(wallet_
.readEntry(folder
, entries
[i
], &value
));
611 base::Pickle
pickle(reinterpret_cast<const char*>(value
.data()),
613 ScopedVector
<autofill::PasswordForm
> forms
=
614 NativeBackendKWalletStub::DeserializeValue(entries
[i
], pickle
);
615 const std::vector
<const PasswordForm
*>& expect
= sorted_expected
[i
].second
;
616 EXPECT_EQ(expect
.size(), forms
.size());
617 for (size_t j
= 0; j
< forms
.size() && j
< expect
.size(); ++j
)
618 CheckPasswordForm(*expect
[j
], *forms
[j
], true);
622 TEST_F(NativeBackendKWalletTest
, NotEnabled
) {
623 NativeBackendKWalletStub
kwallet(42);
624 kwallet_enabled_
= false;
625 EXPECT_FALSE(kwallet
.InitWithBus(mock_session_bus_
));
626 EXPECT_FALSE(klauncher_contacted_
);
629 TEST_F(NativeBackendKWalletTest
, NotRunnable
) {
630 NativeBackendKWalletStub
kwallet(42);
631 kwallet_runnable_
= false;
632 kwallet_running_
= false;
633 EXPECT_FALSE(kwallet
.InitWithBus(mock_session_bus_
));
634 EXPECT_TRUE(klauncher_contacted_
);
637 TEST_F(NativeBackendKWalletTest
, NotRunningOrEnabled
) {
638 NativeBackendKWalletStub
kwallet(42);
639 kwallet_running_
= false;
640 kwallet_enabled_
= false;
641 EXPECT_FALSE(kwallet
.InitWithBus(mock_session_bus_
));
642 EXPECT_TRUE(klauncher_contacted_
);
645 TEST_F(NativeBackendKWalletTest
, NotRunning
) {
646 NativeBackendKWalletStub
kwallet(42);
647 kwallet_running_
= false;
648 EXPECT_TRUE(kwallet
.InitWithBus(mock_session_bus_
));
649 EXPECT_TRUE(klauncher_contacted_
);
652 TEST_F(NativeBackendKWalletTest
, BasicStartup
) {
653 NativeBackendKWalletStub
kwallet(42);
654 EXPECT_TRUE(kwallet
.InitWithBus(mock_session_bus_
));
655 EXPECT_FALSE(klauncher_contacted_
);
658 TEST_F(NativeBackendKWalletTest
, BasicAddLogin
) {
659 NativeBackendKWalletStub
backend(42);
660 EXPECT_TRUE(backend
.InitWithBus(mock_session_bus_
));
662 BrowserThread::PostTask(
663 BrowserThread::DB
, FROM_HERE
,
664 base::Bind(base::IgnoreResult(&NativeBackendKWalletStub::AddLogin
),
665 base::Unretained(&backend
), form_google_
));
669 EXPECT_FALSE(wallet_
.hasFolder("Chrome Form Data"));
671 std::vector
<const PasswordForm
*> forms
;
672 forms
.push_back(&form_google_
);
673 ExpectationArray expected
;
674 expected
.push_back(make_pair(std::string(form_google_
.signon_realm
), forms
));
675 CheckPasswordForms("Chrome Form Data (42)", expected
);
678 TEST_F(NativeBackendKWalletTest
, BasicUpdateLogin
) {
679 NativeBackendKWalletStub
backend(42);
680 EXPECT_TRUE(backend
.InitWithBus(mock_session_bus_
));
682 BrowserThread::PostTask(
683 BrowserThread::DB
, FROM_HERE
,
684 base::Bind(base::IgnoreResult(&NativeBackendKWalletStub::AddLogin
),
685 base::Unretained(&backend
), form_google_
));
689 PasswordForm
new_form_google(form_google_
);
690 new_form_google
.times_used
= 10;
691 new_form_google
.action
= GURL("http://www.google.com/different/login");
694 PasswordStoreChangeList changes
;
695 BrowserThread::PostTask(
696 BrowserThread::DB
, FROM_HERE
,
697 base::Bind(base::IgnoreResult(&NativeBackendKWalletStub::UpdateLogin
),
698 base::Unretained(&backend
),
700 base::Unretained(&changes
)));
703 ASSERT_EQ(1u, changes
.size());
704 EXPECT_EQ(PasswordStoreChange::UPDATE
, changes
.front().type());
705 EXPECT_EQ(new_form_google
, changes
.front().form());
707 std::vector
<const PasswordForm
*> forms
;
708 forms
.push_back(&new_form_google
);
709 ExpectationArray expected
;
710 expected
.push_back(make_pair(std::string(form_google_
.signon_realm
), forms
));
711 CheckPasswordForms("Chrome Form Data (42)", expected
);
714 TEST_F(NativeBackendKWalletTest
, BasicListLogins
) {
715 NativeBackendKWalletStub
backend(42);
716 EXPECT_TRUE(backend
.InitWithBus(mock_session_bus_
));
718 BrowserThread::PostTask(
719 BrowserThread::DB
, FROM_HERE
,
720 base::Bind(base::IgnoreResult(&NativeBackendKWalletStub::AddLogin
),
721 base::Unretained(&backend
), form_google_
));
723 ScopedVector
<autofill::PasswordForm
> form_list
;
724 BrowserThread::PostTask(
725 BrowserThread::DB
, FROM_HERE
,
727 base::IgnoreResult(&NativeBackendKWalletStub::GetAutofillableLogins
),
728 base::Unretained(&backend
), &form_list
));
732 // Quick check that we got something back.
733 EXPECT_EQ(1u, form_list
.size());
735 EXPECT_FALSE(wallet_
.hasFolder("Chrome Form Data"));
737 std::vector
<const PasswordForm
*> forms
;
738 forms
.push_back(&form_google_
);
739 ExpectationArray expected
;
740 expected
.push_back(make_pair(std::string(form_google_
.signon_realm
), forms
));
741 CheckPasswordForms("Chrome Form Data (42)", expected
);
744 TEST_F(NativeBackendKWalletTest
, BasicRemoveLogin
) {
745 NativeBackendKWalletStub
backend(42);
746 EXPECT_TRUE(backend
.InitWithBus(mock_session_bus_
));
748 BrowserThread::PostTask(
749 BrowserThread::DB
, FROM_HERE
,
750 base::Bind(base::IgnoreResult(&NativeBackendKWalletStub::AddLogin
),
751 base::Unretained(&backend
), form_google_
));
755 EXPECT_FALSE(wallet_
.hasFolder("Chrome Form Data"));
757 std::vector
<const PasswordForm
*> forms
;
758 forms
.push_back(&form_google_
);
759 ExpectationArray expected
;
760 expected
.push_back(make_pair(std::string(form_google_
.signon_realm
), forms
));
761 CheckPasswordForms("Chrome Form Data (42)", expected
);
763 BrowserThread::PostTask(
764 BrowserThread::DB
, FROM_HERE
,
765 base::Bind(base::IgnoreResult(&NativeBackendKWalletStub::RemoveLogin
),
766 base::Unretained(&backend
), form_google_
));
771 CheckPasswordForms("Chrome Form Data (42)", expected
);
774 TEST_F(NativeBackendKWalletTest
, UpdateNonexistentLogin
) {
775 NativeBackendKWalletStub
backend(42);
776 EXPECT_TRUE(backend
.InitWithBus(mock_session_bus_
));
778 // First add an unrelated login.
779 BrowserThread::PostTask(
780 BrowserThread::DB
, FROM_HERE
,
781 base::Bind(base::IgnoreResult(&NativeBackendKWalletStub::AddLogin
),
782 base::Unretained(&backend
), form_google_
));
786 std::vector
<const PasswordForm
*> forms
;
787 forms
.push_back(&form_google_
);
788 ExpectationArray expected
;
789 expected
.push_back(make_pair(std::string(form_google_
.signon_realm
), forms
));
790 CheckPasswordForms("Chrome Form Data (42)", expected
);
792 // Attempt to update a login that doesn't exist.
793 PasswordStoreChangeList changes
;
794 BrowserThread::PostTask(
795 BrowserThread::DB
, FROM_HERE
,
796 base::Bind(base::IgnoreResult(&NativeBackendKWalletStub::UpdateLogin
),
797 base::Unretained(&backend
),
799 base::Unretained(&changes
)));
803 EXPECT_EQ(PasswordStoreChangeList(), changes
);
804 CheckPasswordForms("Chrome Form Data (42)", expected
);
807 TEST_F(NativeBackendKWalletTest
, RemoveNonexistentLogin
) {
808 NativeBackendKWalletStub
backend(42);
809 EXPECT_TRUE(backend
.InitWithBus(mock_session_bus_
));
811 // First add an unrelated login.
812 BrowserThread::PostTask(
813 BrowserThread::DB
, FROM_HERE
,
814 base::Bind(base::IgnoreResult(&NativeBackendKWalletStub::AddLogin
),
815 base::Unretained(&backend
), form_google_
));
819 EXPECT_FALSE(wallet_
.hasFolder("Chrome Form Data"));
821 std::vector
<const PasswordForm
*> forms
;
822 forms
.push_back(&form_google_
);
823 ExpectationArray expected
;
824 expected
.push_back(make_pair(std::string(form_google_
.signon_realm
), forms
));
825 CheckPasswordForms("Chrome Form Data (42)", expected
);
827 // Attempt to remove a login that doesn't exist.
828 BrowserThread::PostTask(
829 BrowserThread::DB
, FROM_HERE
,
830 base::Bind(base::IgnoreResult(&NativeBackendKWalletStub::RemoveLogin
),
831 base::Unretained(&backend
), form_isc_
));
833 // Make sure we can still get the first form back.
834 ScopedVector
<autofill::PasswordForm
> form_list
;
835 BrowserThread::PostTask(
836 BrowserThread::DB
, FROM_HERE
,
838 base::IgnoreResult(&NativeBackendKWalletStub::GetAutofillableLogins
),
839 base::Unretained(&backend
), &form_list
));
843 // Quick check that we got something back.
844 EXPECT_EQ(1u, form_list
.size());
846 CheckPasswordForms("Chrome Form Data (42)", expected
);
849 TEST_F(NativeBackendKWalletTest
, AddDuplicateLogin
) {
850 NativeBackendKWalletStub
backend(42);
851 EXPECT_TRUE(backend
.InitWithBus(mock_session_bus_
));
853 PasswordStoreChangeList changes
;
854 changes
.push_back(PasswordStoreChange(PasswordStoreChange::ADD
,
856 BrowserThread::PostTaskAndReplyWithResult(
857 BrowserThread::DB
, FROM_HERE
,
858 base::Bind(&NativeBackendKWalletStub::AddLogin
,
859 base::Unretained(&backend
), form_google_
),
860 base::Bind(&NativeBackendKWalletTest::CheckPasswordChanges
,
864 changes
.push_back(PasswordStoreChange(PasswordStoreChange::REMOVE
,
866 form_google_
.times_used
++;
867 changes
.push_back(PasswordStoreChange(PasswordStoreChange::ADD
,
870 BrowserThread::PostTaskAndReplyWithResult(
871 BrowserThread::DB
, FROM_HERE
,
872 base::Bind(&NativeBackendKWalletStub::AddLogin
,
873 base::Unretained(&backend
), form_google_
),
874 base::Bind(&NativeBackendKWalletTest::CheckPasswordChanges
,
879 EXPECT_FALSE(wallet_
.hasFolder("Chrome Form Data"));
881 std::vector
<const PasswordForm
*> forms
;
882 forms
.push_back(&form_google_
);
883 ExpectationArray expected
;
884 expected
.push_back(make_pair(std::string(form_google_
.signon_realm
), forms
));
885 CheckPasswordForms("Chrome Form Data (42)", expected
);
888 TEST_F(NativeBackendKWalletTest
, AndroidCredentials
) {
889 NativeBackendKWalletStub
backend(42);
890 EXPECT_TRUE(backend
.InitWithBus(mock_session_bus_
));
892 PasswordForm observed_android_form
;
893 observed_android_form
.scheme
= PasswordForm::SCHEME_HTML
;
894 observed_android_form
.signon_realm
=
895 "android://7x7IDboo8u9YKraUsbmVkuf1-@net.rateflix.app/";
896 PasswordForm saved_android_form
= observed_android_form
;
897 saved_android_form
.username_value
= base::UTF8ToUTF16("randomusername");
898 saved_android_form
.password_value
= base::UTF8ToUTF16("password");
900 BrowserThread::PostTask(
901 BrowserThread::DB
, FROM_HERE
,
902 base::Bind(base::IgnoreResult(&NativeBackendKWalletStub::AddLogin
),
903 base::Unretained(&backend
), saved_android_form
));
905 ScopedVector
<autofill::PasswordForm
> form_list
;
906 BrowserThread::PostTask(
907 BrowserThread::DB
, FROM_HERE
,
909 base::IgnoreResult(&NativeBackendKWalletStub::GetLogins
),
910 base::Unretained(&backend
), observed_android_form
, &form_list
));
914 EXPECT_EQ(1u, form_list
.size());
916 std::vector
<const PasswordForm
*> forms
;
917 forms
.push_back(&saved_android_form
);
918 ExpectationArray expected
;
920 make_pair(std::string(saved_android_form
.signon_realm
), forms
));
921 CheckPasswordForms("Chrome Form Data (42)", expected
);
924 TEST_F(NativeBackendKWalletTest
, RemoveLoginsCreatedBetween
) {
925 TestRemoveLoginsBetween(CREATED
);
928 TEST_F(NativeBackendKWalletTest
, RemoveLoginsSyncedBetween
) {
929 TestRemoveLoginsBetween(SYNCED
);
932 // TODO(mdm): add more basic tests here at some point.
933 // (For example tests for storing >1 password per realm pickle.)
935 class NativeBackendKWalletPickleTest
: public NativeBackendKWalletTestBase
{
937 // Based on |form|, fills |pickle| with data conforming to
938 // |effective_version|, but marking the pickle version as |stored_version|. In
939 // most cases the two versions should be the same.
940 void CreateVersion1PlusPickle(const PasswordForm
& form
,
941 base::Pickle
* pickle
,
943 int effective_version
);
944 void CreateVersion0Pickle(bool size_32
,
945 const PasswordForm
& form
,
946 base::Pickle
* pickle
);
947 // As explained in http://crbug.com/494229#c11, version 6 added a new optional
948 // field to version 5. This field became required in version 7. Depending on
949 // |with_optional_field|, this method checks deserialization with or without
950 // the optional field.
951 void CheckVersion6Pickle(bool with_optional_field
);
952 void CheckVersion5Pickle();
953 void CheckVersion3Pickle();
954 void CheckVersion2Pickle();
955 void CheckVersion1Pickle();
956 void CheckVersion0Pickle(bool size_32
, PasswordForm::Scheme scheme
);
959 // Creates a Pickle from |form|. If |size_32| is true, stores the number of
960 // forms in the pickle as a 32bit uint, otherwise as 64 bit size_t. The latter
961 // should be the case for versions > 0. If |date_created_internal| is true,
962 // stores |date_created| as base::Time's internal value, otherwise as time_t.
963 void CreatePickle(bool size_32
,
964 bool date_created_internal
,
965 const PasswordForm
& form
,
966 base::Pickle
* pickle
);
969 void NativeBackendKWalletPickleTest::CreateVersion1PlusPickle(
970 const PasswordForm
& form
,
971 base::Pickle
* pickle
,
973 int effective_version
) {
974 pickle
->WriteInt(stored_version
);
975 CreatePickle(false, true, form
, pickle
);
976 if (effective_version
< 2)
978 pickle
->WriteInt(form
.type
);
979 pickle
->WriteInt(form
.times_used
);
980 autofill::SerializeFormData(form
.form_data
, pickle
);
981 if (effective_version
< 3)
983 pickle
->WriteInt64(form
.date_synced
.ToInternalValue());
984 if (effective_version
< 4)
986 pickle
->WriteString16(form
.display_name
);
987 pickle
->WriteString(form
.icon_url
.spec());
988 pickle
->WriteString(form
.federation_url
.spec());
989 pickle
->WriteBool(form
.skip_zero_click
);
990 if (effective_version
< 7)
992 pickle
->WriteInt(form
.generation_upload_status
);
995 void NativeBackendKWalletPickleTest::CreateVersion0Pickle(
997 const PasswordForm
& form
,
998 base::Pickle
* pickle
) {
1000 CreatePickle(size_32
, false, form
, pickle
);
1003 void NativeBackendKWalletPickleTest::CreatePickle(bool size_32
,
1004 bool date_created_internal
,
1005 const PasswordForm
& form
,
1006 base::Pickle
* pickle
) {
1008 pickle
->WriteUInt32(1); // Size of form list. 32 bits.
1010 pickle
->WriteSizeT(1); // Size of form list. 64 bits.
1011 pickle
->WriteInt(form
.scheme
);
1012 pickle
->WriteString(form
.origin
.spec());
1013 pickle
->WriteString(form
.action
.spec());
1014 pickle
->WriteString16(form
.username_element
);
1015 pickle
->WriteString16(form
.username_value
);
1016 pickle
->WriteString16(form
.password_element
);
1017 pickle
->WriteString16(form
.password_value
);
1018 pickle
->WriteString16(form
.submit_element
);
1019 pickle
->WriteBool(form
.ssl_valid
);
1020 pickle
->WriteBool(form
.preferred
);
1021 pickle
->WriteBool(form
.blacklisted_by_user
);
1022 if (date_created_internal
)
1023 pickle
->WriteInt64(form
.date_created
.ToInternalValue());
1025 pickle
->WriteInt64(form
.date_created
.ToTimeT());
1028 void NativeBackendKWalletPickleTest::CheckVersion6Pickle(
1029 bool with_optional_field
) {
1030 base::Pickle pickle
;
1031 PasswordForm form
= form_google_
;
1032 if (!with_optional_field
) {
1033 PasswordForm default_values
;
1034 form
.generation_upload_status
= default_values
.generation_upload_status
;
1036 CreateVersion1PlusPickle(form
, &pickle
, 6, with_optional_field
? 7 : 5);
1038 ScopedVector
<PasswordForm
> form_list
=
1039 NativeBackendKWalletStub::DeserializeValue(form
.signon_realm
, pickle
);
1041 EXPECT_EQ(1u, form_list
.size());
1042 if (form_list
.size() > 0)
1043 CheckPasswordForm(form
, *form_list
[0], true);
1047 void NativeBackendKWalletPickleTest::CheckVersion5Pickle() {
1048 base::Pickle pickle
;
1049 PasswordForm default_values
;
1050 PasswordForm form
= form_google_
;
1051 // Remove the field which was not present in version #5.
1052 form
.generation_upload_status
= default_values
.generation_upload_status
;
1053 CreateVersion1PlusPickle(form
, &pickle
, 5, 5);
1055 ScopedVector
<PasswordForm
> form_list
=
1056 NativeBackendKWalletStub::DeserializeValue(form
.signon_realm
, pickle
);
1058 EXPECT_EQ(1u, form_list
.size());
1059 if (form_list
.size() > 0)
1060 CheckPasswordForm(form
, *form_list
[0], true);
1063 void NativeBackendKWalletPickleTest::CheckVersion3Pickle() {
1064 base::Pickle pickle
;
1065 PasswordForm default_values
;
1066 PasswordForm form
= form_google_
;
1067 // Remove the fields which were not present in version #3.
1068 form
.display_name
= default_values
.display_name
;
1069 form
.icon_url
= default_values
.icon_url
;
1070 form
.federation_url
= default_values
.federation_url
;
1071 form
.skip_zero_click
= default_values
.skip_zero_click
;
1072 form
.generation_upload_status
= default_values
.generation_upload_status
;
1073 CreateVersion1PlusPickle(form
, &pickle
, 3, 3);
1075 ScopedVector
<PasswordForm
> form_list
=
1076 NativeBackendKWalletStub::DeserializeValue(form
.signon_realm
, pickle
);
1078 EXPECT_EQ(1u, form_list
.size());
1079 if (form_list
.size() > 0)
1080 CheckPasswordForm(form
, *form_list
[0], false);
1083 void NativeBackendKWalletPickleTest::CheckVersion2Pickle() {
1084 base::Pickle pickle
;
1085 PasswordForm form
= old_form_google_
;
1086 form
.times_used
= form_google_
.times_used
;
1087 form
.type
= form_google_
.type
;
1088 form
.form_data
= form_google_
.form_data
;
1089 CreateVersion1PlusPickle(form
, &pickle
, 2, 2);
1091 ScopedVector
<PasswordForm
> form_list
=
1092 NativeBackendKWalletStub::DeserializeValue(form
.signon_realm
, pickle
);
1094 EXPECT_EQ(1u, form_list
.size());
1095 if (form_list
.size() > 0)
1096 CheckPasswordForm(form
, *form_list
[0], false);
1099 // Make sure that we can still read version 1 pickles.
1100 void NativeBackendKWalletPickleTest::CheckVersion1Pickle() {
1101 base::Pickle pickle
;
1102 PasswordForm form
= form_google_
;
1103 CreateVersion1PlusPickle(form
, &pickle
, 1, 1);
1105 ScopedVector
<autofill::PasswordForm
> form_list
=
1106 NativeBackendKWalletStub::DeserializeValue(form
.signon_realm
, pickle
);
1108 // This will match |old_form_google_| because not all the fields present in
1109 // |form_google_| will be deserialized.
1110 EXPECT_EQ(1u, form_list
.size());
1111 if (form_list
.size() > 0)
1112 CheckPasswordForm(old_form_google_
, *form_list
[0], false);
1115 void NativeBackendKWalletPickleTest::CheckVersion0Pickle(
1116 bool size_32
, PasswordForm::Scheme scheme
) {
1117 base::Pickle pickle
;
1118 PasswordForm form
= old_form_google_
;
1119 form
.scheme
= scheme
;
1120 CreateVersion0Pickle(size_32
, form
, &pickle
);
1121 ScopedVector
<autofill::PasswordForm
> form_list
=
1122 NativeBackendKWalletStub::DeserializeValue(form
.signon_realm
, pickle
);
1123 EXPECT_EQ(1u, form_list
.size());
1124 if (form_list
.size() > 0)
1125 CheckPasswordForm(form
, *form_list
[0], false);
1128 // Check that if KWallet fails to respond, the backend propagates the error.
1129 TEST_F(NativeBackendKWalletTest
, GetAllLoginsErrorHandling
) {
1130 NativeBackendKWalletStub
backend(42);
1131 EXPECT_TRUE(backend
.InitWithBus(mock_session_bus_
));
1132 // Make KWallet fail on calling readEntry.
1133 failing_methods_
.insert("readEntry");
1135 // Store some non-blacklisted logins to be potentially returned.
1136 BrowserThread::PostTask(
1137 BrowserThread::DB
, FROM_HERE
,
1138 base::Bind(base::IgnoreResult(&NativeBackendKWalletStub::AddLogin
),
1139 base::Unretained(&backend
), form_google_
));
1141 // Verify that nothing is in fact returned, because KWallet fails to respond.
1142 ScopedVector
<autofill::PasswordForm
> form_list
;
1143 BrowserThread::PostTask(BrowserThread::DB
, FROM_HERE
,
1144 base::Bind(&CheckGetAutofillableLoginsFails
,
1145 base::Unretained(&backend
), &form_list
));
1147 EXPECT_EQ(0u, form_list
.size());
1150 // We try both SCHEME_HTML and SCHEME_BASIC since the scheme is stored right
1151 // after the size in the pickle, so it's what gets read as part of the count
1152 // when reading 32-bit pickles on 64-bit systems. SCHEME_HTML is 0 (so we'll
1153 // detect errors later) while SCHEME_BASIC is 1 (so we'll detect it then). We
1154 // try both 32-bit and 64-bit pickles since only one will be the "other" size
1155 // for whatever architecture we're running on, but we want to make sure we can
1156 // read all combinations in any event.
1158 TEST_F(NativeBackendKWalletPickleTest
, ReadsOld32BitHTMLPickles
) {
1159 CheckVersion0Pickle(true, PasswordForm::SCHEME_HTML
);
1162 TEST_F(NativeBackendKWalletPickleTest
, ReadsOld32BitHTTPPickles
) {
1163 CheckVersion0Pickle(true, PasswordForm::SCHEME_BASIC
);
1166 TEST_F(NativeBackendKWalletPickleTest
, ReadsOld64BitHTMLPickles
) {
1167 CheckVersion0Pickle(false, PasswordForm::SCHEME_HTML
);
1170 TEST_F(NativeBackendKWalletPickleTest
, ReadsOld64BitHTTPPickles
) {
1171 CheckVersion0Pickle(false, PasswordForm::SCHEME_BASIC
);
1174 TEST_F(NativeBackendKWalletPickleTest
, CheckVersion1Pickle
) {
1175 CheckVersion1Pickle();
1178 TEST_F(NativeBackendKWalletPickleTest
, CheckVersion2Pickle
) {
1179 CheckVersion2Pickle();
1182 TEST_F(NativeBackendKWalletPickleTest
, CheckVersion3Pickle
) {
1183 CheckVersion3Pickle();
1186 TEST_F(NativeBackendKWalletPickleTest
, CheckVersion5Pickle
) {
1187 CheckVersion5Pickle();
1190 TEST_F(NativeBackendKWalletPickleTest
, CheckVersion6Pickle
) {
1191 CheckVersion6Pickle(false);
1192 CheckVersion6Pickle(true);