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 void CheckTrue(bool result
) {
138 } // anonymous namespace
140 // Obscure magic: we need to declare storage for this constant because we use it
141 // in ways that require its address in this test, but not in the actual code.
142 const int NativeBackendKWallet::kInvalidKWalletHandle
;
144 // Subclass NativeBackendKWallet to promote some members to public for testing.
145 class NativeBackendKWalletStub
: public NativeBackendKWallet
{
147 explicit NativeBackendKWalletStub(LocalProfileId id
)
148 : NativeBackendKWallet(id
) {
150 using NativeBackendKWallet::InitWithBus
;
151 using NativeBackendKWallet::kInvalidKWalletHandle
;
152 using NativeBackendKWallet::DeserializeValue
;
155 // Provide some test forms to avoid having to set them up in each test.
156 class NativeBackendKWalletTestBase
: public testing::Test
{
158 NativeBackendKWalletTestBase() {
159 old_form_google_
.origin
= GURL("http://www.google.com/");
160 old_form_google_
.action
= GURL("http://www.google.com/login");
161 old_form_google_
.username_element
= UTF8ToUTF16("user");
162 old_form_google_
.username_value
= UTF8ToUTF16("joeschmoe");
163 old_form_google_
.password_element
= UTF8ToUTF16("pass");
164 old_form_google_
.password_value
= UTF8ToUTF16("seekrit");
165 old_form_google_
.submit_element
= UTF8ToUTF16("submit");
166 old_form_google_
.signon_realm
= "Google";
167 old_form_google_
.date_created
= base::Time::Now();
169 form_google_
= old_form_google_
;
170 form_google_
.times_used
= 3;
171 form_google_
.type
= PasswordForm::TYPE_GENERATED
;
172 form_google_
.form_data
.name
= UTF8ToUTF16("form_name");
173 form_google_
.date_synced
= base::Time::Now();
174 form_google_
.date_created
= old_form_google_
.date_created
;
175 form_google_
.display_name
= UTF8ToUTF16("Joe Schmoe");
176 form_google_
.icon_url
= GURL("http://www.google.com/icon");
177 form_google_
.federation_url
= GURL("http://www.google.com/federation_url");
178 form_google_
.skip_zero_click
= true;
179 form_google_
.generation_upload_status
= PasswordForm::NEGATIVE_SIGNAL_SENT
;
181 form_isc_
.origin
= GURL("http://www.isc.org/");
182 form_isc_
.action
= GURL("http://www.isc.org/auth");
183 form_isc_
.username_element
= UTF8ToUTF16("id");
184 form_isc_
.username_value
= UTF8ToUTF16("janedoe");
185 form_isc_
.password_element
= UTF8ToUTF16("passwd");
186 form_isc_
.password_value
= UTF8ToUTF16("ihazabukkit");
187 form_isc_
.submit_element
= UTF8ToUTF16("login");
188 form_isc_
.signon_realm
= "ISC";
189 form_isc_
.date_synced
= base::Time::Now();
190 form_isc_
.date_created
= base::Time::Now();
193 static void CheckPasswordForm(const PasswordForm
& expected
,
194 const PasswordForm
& actual
,
195 bool check_date_created
);
196 static void CheckPasswordChanges(const PasswordStoreChangeList
& expected
,
197 const PasswordStoreChangeList
& actual
);
198 static void CheckPasswordChangesWithResult(
199 const PasswordStoreChangeList
* expected
,
200 const PasswordStoreChangeList
* actual
,
203 PasswordForm old_form_google_
;
204 PasswordForm form_google_
;
205 PasswordForm form_isc_
;
209 void NativeBackendKWalletTestBase::CheckPasswordForm(
210 const PasswordForm
& expected
,
211 const PasswordForm
& actual
,
212 bool check_date_created
) {
213 EXPECT_EQ(expected
.origin
, actual
.origin
);
214 EXPECT_EQ(expected
.password_value
, actual
.password_value
);
215 EXPECT_EQ(expected
.action
, actual
.action
);
216 EXPECT_EQ(expected
.username_element
, actual
.username_element
);
217 EXPECT_EQ(expected
.username_value
, actual
.username_value
);
218 EXPECT_EQ(expected
.password_element
, actual
.password_element
);
219 EXPECT_EQ(expected
.submit_element
, actual
.submit_element
);
220 EXPECT_EQ(expected
.signon_realm
, actual
.signon_realm
);
221 EXPECT_EQ(expected
.ssl_valid
, actual
.ssl_valid
);
222 EXPECT_EQ(expected
.preferred
, actual
.preferred
);
223 if (check_date_created
) {
224 EXPECT_EQ(expected
.date_created
, actual
.date_created
);
226 EXPECT_EQ(expected
.blacklisted_by_user
, actual
.blacklisted_by_user
);
227 EXPECT_EQ(expected
.type
, actual
.type
);
228 EXPECT_EQ(expected
.times_used
, actual
.times_used
);
229 EXPECT_EQ(expected
.scheme
, actual
.scheme
);
230 EXPECT_EQ(expected
.date_synced
, actual
.date_synced
);
231 EXPECT_EQ(expected
.display_name
, actual
.display_name
);
232 EXPECT_EQ(expected
.icon_url
, actual
.icon_url
);
233 EXPECT_EQ(expected
.federation_url
, actual
.federation_url
);
234 EXPECT_EQ(expected
.skip_zero_click
, actual
.skip_zero_click
);
235 EXPECT_EQ(expected
.generation_upload_status
, actual
.generation_upload_status
);
239 void NativeBackendKWalletTestBase::CheckPasswordChanges(
240 const PasswordStoreChangeList
& expected
,
241 const PasswordStoreChangeList
& actual
) {
242 ASSERT_EQ(expected
.size(), actual
.size());
243 for (size_t i
= 0; i
< expected
.size(); ++i
) {
244 EXPECT_EQ(expected
[i
].type(), actual
[i
].type());
245 CheckPasswordForm(expected
[i
].form(), actual
[i
].form(), true);
250 void NativeBackendKWalletTestBase::CheckPasswordChangesWithResult(
251 const PasswordStoreChangeList
* expected
,
252 const PasswordStoreChangeList
* actual
,
255 CheckPasswordChanges(*expected
, *actual
);
258 class NativeBackendKWalletTest
: public NativeBackendKWalletTestBase
{
260 NativeBackendKWalletTest()
261 : ui_thread_(BrowserThread::UI
, &message_loop_
),
262 db_thread_(BrowserThread::DB
), klauncher_ret_(0),
263 klauncher_contacted_(false), kwallet_runnable_(true),
264 kwallet_running_(true), kwallet_enabled_(true) {
267 void SetUp() override
;
268 void TearDown() override
;
270 // Let the DB thread run to completion of all current tasks.
272 base::WaitableEvent
event(false, false);
273 BrowserThread::PostTask(BrowserThread::DB
, FROM_HERE
,
274 base::Bind(ThreadDone
, &event
));
276 // Some of the tests may post messages to the UI thread, but we don't need
277 // to run those until after the DB thread is finished. So run it here.
278 message_loop_
.RunUntilIdle();
280 static void ThreadDone(base::WaitableEvent
* event
) {
284 // Utilities to help verify sets of expectations.
286 std::pair
<std::string
,
287 std::vector
<const PasswordForm
*> > > ExpectationArray
;
288 void CheckPasswordForms(const std::string
& folder
,
289 const ExpectationArray
& sorted_expected
);
291 enum RemoveBetweenMethod
{
296 // Tests RemoveLoginsCreatedBetween or RemoveLoginsSyncedBetween.
297 void TestRemoveLoginsBetween(RemoveBetweenMethod date_to_test
);
299 base::MessageLoopForUI message_loop_
;
300 content::TestBrowserThread ui_thread_
;
301 content::TestBrowserThread db_thread_
;
303 scoped_refptr
<dbus::MockBus
> mock_session_bus_
;
304 scoped_refptr
<dbus::MockObjectProxy
> mock_klauncher_proxy_
;
305 scoped_refptr
<dbus::MockObjectProxy
> mock_kwallet_proxy_
;
308 std::string klauncher_error_
;
309 bool klauncher_contacted_
;
311 bool kwallet_runnable_
;
312 bool kwallet_running_
;
313 bool kwallet_enabled_
;
317 // For all method names contained in |failing_methods_|, the mocked KWallet
318 // will return a null response.
319 std::set
<std::string
> failing_methods_
;
322 dbus::Response
* KLauncherMethodCall(
323 dbus::MethodCall
* method_call
, testing::Unused
);
325 dbus::Response
* KWalletMethodCall(
326 dbus::MethodCall
* method_call
, testing::Unused
);
329 void NativeBackendKWalletTest::SetUp() {
330 ASSERT_TRUE(db_thread_
.Start());
332 dbus::Bus::Options options
;
333 options
.bus_type
= dbus::Bus::SESSION
;
334 mock_session_bus_
= new dbus::MockBus(options
);
336 mock_klauncher_proxy_
=
337 new dbus::MockObjectProxy(mock_session_bus_
.get(),
339 dbus::ObjectPath("/KLauncher"));
340 EXPECT_CALL(*mock_klauncher_proxy_
.get(), MockCallMethodAndBlock(_
, _
))
342 Invoke(this, &NativeBackendKWalletTest::KLauncherMethodCall
));
344 mock_kwallet_proxy_
=
345 new dbus::MockObjectProxy(mock_session_bus_
.get(),
347 dbus::ObjectPath("/modules/kwalletd"));
348 EXPECT_CALL(*mock_kwallet_proxy_
.get(), MockCallMethodAndBlock(_
, _
))
350 Invoke(this, &NativeBackendKWalletTest::KWalletMethodCall
));
353 *mock_session_bus_
.get(),
354 GetObjectProxy("org.kde.klauncher", dbus::ObjectPath("/KLauncher")))
355 .WillRepeatedly(Return(mock_klauncher_proxy_
.get()));
357 *mock_session_bus_
.get(),
358 GetObjectProxy("org.kde.kwalletd", dbus::ObjectPath("/modules/kwalletd")))
359 .WillRepeatedly(Return(mock_kwallet_proxy_
.get()));
361 EXPECT_CALL(*mock_session_bus_
.get(), ShutdownAndBlock()).WillOnce(Return())
362 .WillRepeatedly(Return());
365 void NativeBackendKWalletTest::TearDown() {
366 base::ThreadTaskRunnerHandle::Get()->PostTask(
367 FROM_HERE
, base::MessageLoop::QuitClosure());
368 base::MessageLoop::current()->Run();
372 void NativeBackendKWalletTest::TestRemoveLoginsBetween(
373 RemoveBetweenMethod date_to_test
) {
374 NativeBackendKWalletStub
backend(42);
375 EXPECT_TRUE(backend
.InitWithBus(mock_session_bus_
));
377 form_google_
.date_synced
= base::Time();
378 form_isc_
.date_synced
= base::Time();
379 form_google_
.date_created
= base::Time();
380 form_isc_
.date_created
= base::Time();
381 base::Time now
= base::Time::Now();
382 base::Time next_day
= now
+ base::TimeDelta::FromDays(1);
383 if (date_to_test
== CREATED
) {
384 form_google_
.date_created
= now
;
385 form_isc_
.date_created
= next_day
;
387 form_google_
.date_synced
= now
;
388 form_isc_
.date_synced
= next_day
;
391 BrowserThread::PostTask(
394 base::Bind(base::IgnoreResult(&NativeBackendKWalletStub::AddLogin
),
395 base::Unretained(&backend
),
397 BrowserThread::PostTask(
400 base::Bind(base::IgnoreResult(&NativeBackendKWalletStub::AddLogin
),
401 base::Unretained(&backend
),
404 PasswordStoreChangeList expected_changes
;
405 expected_changes
.push_back(
406 PasswordStoreChange(PasswordStoreChange::REMOVE
, form_google_
));
407 PasswordStoreChangeList changes
;
408 bool (NativeBackendKWallet::*method
)(
409 base::Time
, base::Time
, password_manager::PasswordStoreChangeList
*) =
410 date_to_test
== CREATED
411 ? &NativeBackendKWalletStub::RemoveLoginsCreatedBetween
412 : &NativeBackendKWalletStub::RemoveLoginsSyncedBetween
;
413 BrowserThread::PostTaskAndReplyWithResult(
417 method
, base::Unretained(&backend
), base::Time(), next_day
, &changes
),
418 base::Bind(&CheckPasswordChangesWithResult
, &expected_changes
, &changes
));
421 std::vector
<const PasswordForm
*> forms
;
422 forms
.push_back(&form_isc_
);
423 ExpectationArray expected
;
424 expected
.push_back(make_pair(std::string(form_isc_
.signon_realm
), forms
));
425 CheckPasswordForms("Chrome Form Data (42)", expected
);
428 expected_changes
.clear();
429 expected_changes
.push_back(
430 PasswordStoreChange(PasswordStoreChange::REMOVE
, form_isc_
));
431 BrowserThread::PostTaskAndReplyWithResult(
435 method
, base::Unretained(&backend
), next_day
, base::Time(), &changes
),
436 base::Bind(&CheckPasswordChangesWithResult
, &expected_changes
, &changes
));
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::PostTaskAndReplyWithResult(
663 BrowserThread::DB
, FROM_HERE
,
664 base::Bind(&NativeBackendKWalletStub::AddLogin
,
665 base::Unretained(&backend
), form_google_
),
666 base::Bind(&CheckPasswordChanges
,
667 PasswordStoreChangeList(1, PasswordStoreChange(
668 PasswordStoreChange::ADD
, form_google_
))));
672 EXPECT_FALSE(wallet_
.hasFolder("Chrome Form Data"));
674 std::vector
<const PasswordForm
*> forms
;
675 forms
.push_back(&form_google_
);
676 ExpectationArray expected
;
677 expected
.push_back(make_pair(std::string(form_google_
.signon_realm
), forms
));
678 CheckPasswordForms("Chrome Form Data (42)", expected
);
681 TEST_F(NativeBackendKWalletTest
, BasicUpdateLogin
) {
682 NativeBackendKWalletStub
backend(42);
683 EXPECT_TRUE(backend
.InitWithBus(mock_session_bus_
));
685 BrowserThread::PostTask(
686 BrowserThread::DB
, FROM_HERE
,
687 base::Bind(base::IgnoreResult(&NativeBackendKWalletStub::AddLogin
),
688 base::Unretained(&backend
), form_google_
));
692 PasswordForm
new_form_google(form_google_
);
693 new_form_google
.times_used
= 10;
694 new_form_google
.action
= GURL("http://www.google.com/different/login");
697 PasswordStoreChangeList changes
;
698 PasswordStoreChangeList
expected_changes(
699 1, PasswordStoreChange(PasswordStoreChange::UPDATE
, new_form_google
));
700 BrowserThread::PostTaskAndReplyWithResult(
701 BrowserThread::DB
, FROM_HERE
,
702 base::Bind(&NativeBackendKWalletStub::UpdateLogin
,
703 base::Unretained(&backend
),
706 base::Bind(&CheckPasswordChangesWithResult
, &expected_changes
, &changes
));
709 ASSERT_EQ(1u, changes
.size());
710 EXPECT_EQ(PasswordStoreChange::UPDATE
, changes
.front().type());
711 EXPECT_EQ(new_form_google
, changes
.front().form());
713 std::vector
<const PasswordForm
*> forms
;
714 forms
.push_back(&new_form_google
);
715 ExpectationArray expected
;
716 expected
.push_back(make_pair(std::string(form_google_
.signon_realm
), forms
));
717 CheckPasswordForms("Chrome Form Data (42)", expected
);
720 TEST_F(NativeBackendKWalletTest
, BasicListLogins
) {
721 NativeBackendKWalletStub
backend(42);
722 EXPECT_TRUE(backend
.InitWithBus(mock_session_bus_
));
724 BrowserThread::PostTask(
725 BrowserThread::DB
, FROM_HERE
,
726 base::Bind(base::IgnoreResult(&NativeBackendKWalletStub::AddLogin
),
727 base::Unretained(&backend
), form_google_
));
729 ScopedVector
<autofill::PasswordForm
> form_list
;
730 BrowserThread::PostTaskAndReplyWithResult(
731 BrowserThread::DB
, FROM_HERE
,
732 base::Bind(&NativeBackendKWalletStub::GetAutofillableLogins
,
733 base::Unretained(&backend
), &form_list
),
734 base::Bind(&CheckTrue
));
738 // Quick check that we got something back.
739 EXPECT_EQ(1u, form_list
.size());
741 EXPECT_FALSE(wallet_
.hasFolder("Chrome Form Data"));
743 std::vector
<const PasswordForm
*> forms
;
744 forms
.push_back(&form_google_
);
745 ExpectationArray expected
;
746 expected
.push_back(make_pair(std::string(form_google_
.signon_realm
), forms
));
747 CheckPasswordForms("Chrome Form Data (42)", expected
);
750 TEST_F(NativeBackendKWalletTest
, BasicRemoveLogin
) {
751 NativeBackendKWalletStub
backend(42);
752 EXPECT_TRUE(backend
.InitWithBus(mock_session_bus_
));
754 BrowserThread::PostTask(
755 BrowserThread::DB
, FROM_HERE
,
756 base::Bind(base::IgnoreResult(&NativeBackendKWalletStub::AddLogin
),
757 base::Unretained(&backend
), form_google_
));
761 EXPECT_FALSE(wallet_
.hasFolder("Chrome Form Data"));
763 std::vector
<const PasswordForm
*> forms
;
764 forms
.push_back(&form_google_
);
765 ExpectationArray expected
;
766 expected
.push_back(make_pair(std::string(form_google_
.signon_realm
), forms
));
767 CheckPasswordForms("Chrome Form Data (42)", expected
);
769 PasswordStoreChangeList changes
;
770 PasswordStoreChangeList
expected_changes(
771 1, PasswordStoreChange(PasswordStoreChange::REMOVE
, form_google_
));
772 BrowserThread::PostTaskAndReplyWithResult(
773 BrowserThread::DB
, FROM_HERE
,
774 base::Bind(&NativeBackendKWalletStub::RemoveLogin
,
775 base::Unretained(&backend
), form_google_
, &changes
),
776 base::Bind(&CheckPasswordChangesWithResult
, &expected_changes
, &changes
));
781 CheckPasswordForms("Chrome Form Data (42)", expected
);
784 TEST_F(NativeBackendKWalletTest
, UpdateNonexistentLogin
) {
785 NativeBackendKWalletStub
backend(42);
786 EXPECT_TRUE(backend
.InitWithBus(mock_session_bus_
));
788 // First add an unrelated login.
789 BrowserThread::PostTask(
790 BrowserThread::DB
, FROM_HERE
,
791 base::Bind(base::IgnoreResult(&NativeBackendKWalletStub::AddLogin
),
792 base::Unretained(&backend
), form_google_
));
796 std::vector
<const PasswordForm
*> forms
;
797 forms
.push_back(&form_google_
);
798 ExpectationArray expected
;
799 expected
.push_back(make_pair(std::string(form_google_
.signon_realm
), forms
));
800 CheckPasswordForms("Chrome Form Data (42)", expected
);
802 // Attempt to update a login that doesn't exist.
803 PasswordStoreChangeList changes
;
804 BrowserThread::PostTaskAndReplyWithResult(
805 BrowserThread::DB
, FROM_HERE
,
806 base::Bind(&NativeBackendKWalletStub::UpdateLogin
,
807 base::Unretained(&backend
),
810 base::Bind(&CheckPasswordChangesWithResult
,
811 base::Owned(new PasswordStoreChangeList
), &changes
));
815 EXPECT_EQ(PasswordStoreChangeList(), changes
);
816 CheckPasswordForms("Chrome Form Data (42)", expected
);
819 TEST_F(NativeBackendKWalletTest
, RemoveNonexistentLogin
) {
820 NativeBackendKWalletStub
backend(42);
821 EXPECT_TRUE(backend
.InitWithBus(mock_session_bus_
));
823 // First add an unrelated login.
824 BrowserThread::PostTask(
825 BrowserThread::DB
, FROM_HERE
,
826 base::Bind(base::IgnoreResult(&NativeBackendKWalletStub::AddLogin
),
827 base::Unretained(&backend
), form_google_
));
831 EXPECT_FALSE(wallet_
.hasFolder("Chrome Form Data"));
833 std::vector
<const PasswordForm
*> forms
;
834 forms
.push_back(&form_google_
);
835 ExpectationArray expected
;
836 expected
.push_back(make_pair(std::string(form_google_
.signon_realm
), forms
));
837 CheckPasswordForms("Chrome Form Data (42)", expected
);
839 // Attempt to remove a login that doesn't exist.
840 PasswordStoreChangeList changes
;
841 BrowserThread::PostTaskAndReplyWithResult(
842 BrowserThread::DB
, FROM_HERE
,
843 base::Bind(&NativeBackendKWalletStub::RemoveLogin
,
844 base::Unretained(&backend
), form_isc_
, &changes
),
845 base::Bind(&CheckPasswordChangesWithResult
,
846 base::Owned(new PasswordStoreChangeList
), &changes
));
848 // Make sure we can still get the first form back.
849 ScopedVector
<autofill::PasswordForm
> form_list
;
850 BrowserThread::PostTaskAndReplyWithResult(
851 BrowserThread::DB
, FROM_HERE
,
852 base::Bind(&NativeBackendKWalletStub::GetAutofillableLogins
,
853 base::Unretained(&backend
), &form_list
),
854 base::Bind(&CheckTrue
));
858 // Quick check that we got something back.
859 EXPECT_EQ(1u, form_list
.size());
861 CheckPasswordForms("Chrome Form Data (42)", expected
);
864 TEST_F(NativeBackendKWalletTest
, AddDuplicateLogin
) {
865 NativeBackendKWalletStub
backend(42);
866 EXPECT_TRUE(backend
.InitWithBus(mock_session_bus_
));
868 PasswordStoreChangeList changes
;
869 changes
.push_back(PasswordStoreChange(PasswordStoreChange::ADD
,
871 BrowserThread::PostTaskAndReplyWithResult(
872 BrowserThread::DB
, FROM_HERE
,
873 base::Bind(&NativeBackendKWalletStub::AddLogin
,
874 base::Unretained(&backend
), form_google_
),
875 base::Bind(&NativeBackendKWalletTest::CheckPasswordChanges
,
879 changes
.push_back(PasswordStoreChange(PasswordStoreChange::REMOVE
,
881 form_google_
.times_used
++;
882 form_google_
.submit_element
= UTF8ToUTF16("submit2");
883 changes
.push_back(PasswordStoreChange(PasswordStoreChange::ADD
,
886 BrowserThread::PostTaskAndReplyWithResult(
887 BrowserThread::DB
, FROM_HERE
,
888 base::Bind(&NativeBackendKWalletStub::AddLogin
,
889 base::Unretained(&backend
), form_google_
),
890 base::Bind(&NativeBackendKWalletTest::CheckPasswordChanges
,
895 EXPECT_FALSE(wallet_
.hasFolder("Chrome Form Data"));
897 std::vector
<const PasswordForm
*> forms
;
898 forms
.push_back(&form_google_
);
899 ExpectationArray expected
;
900 expected
.push_back(make_pair(std::string(form_google_
.signon_realm
), forms
));
901 CheckPasswordForms("Chrome Form Data (42)", expected
);
904 TEST_F(NativeBackendKWalletTest
, AndroidCredentials
) {
905 NativeBackendKWalletStub
backend(42);
906 EXPECT_TRUE(backend
.InitWithBus(mock_session_bus_
));
908 PasswordForm observed_android_form
;
909 observed_android_form
.scheme
= PasswordForm::SCHEME_HTML
;
910 observed_android_form
.signon_realm
=
911 "android://7x7IDboo8u9YKraUsbmVkuf1-@net.rateflix.app/";
912 PasswordForm saved_android_form
= observed_android_form
;
913 saved_android_form
.username_value
= base::UTF8ToUTF16("randomusername");
914 saved_android_form
.password_value
= base::UTF8ToUTF16("password");
916 BrowserThread::PostTaskAndReplyWithResult(
917 BrowserThread::DB
, FROM_HERE
,
918 base::Bind(&NativeBackendKWalletStub::AddLogin
,
919 base::Unretained(&backend
), saved_android_form
),
920 base::Bind(&CheckPasswordChanges
,
921 PasswordStoreChangeList(1, PasswordStoreChange(
922 PasswordStoreChange::ADD
, saved_android_form
))));
924 ScopedVector
<autofill::PasswordForm
> form_list
;
925 BrowserThread::PostTaskAndReplyWithResult(
926 BrowserThread::DB
, FROM_HERE
,
927 base::Bind(&NativeBackendKWalletStub::GetLogins
,
928 base::Unretained(&backend
), observed_android_form
, &form_list
),
929 base::Bind(&CheckTrue
));
933 EXPECT_EQ(1u, form_list
.size());
935 std::vector
<const PasswordForm
*> forms
;
936 forms
.push_back(&saved_android_form
);
937 ExpectationArray expected
;
939 make_pair(std::string(saved_android_form
.signon_realm
), forms
));
940 CheckPasswordForms("Chrome Form Data (42)", expected
);
943 TEST_F(NativeBackendKWalletTest
, RemoveLoginsCreatedBetween
) {
944 TestRemoveLoginsBetween(CREATED
);
947 TEST_F(NativeBackendKWalletTest
, RemoveLoginsSyncedBetween
) {
948 TestRemoveLoginsBetween(SYNCED
);
951 TEST_F(NativeBackendKWalletTest
, ReadDuplicateForms
) {
952 NativeBackendKWalletStub
backend(42);
953 EXPECT_TRUE(backend
.InitWithBus(mock_session_bus_
));
955 // Add 2 slightly different password forms.
956 const char unique_string
[] = "unique_unique_string";
957 const char unique_string_replacement
[] = "uniKue_unique_string";
958 form_google_
.origin
=
959 GURL(std::string("http://www.google.com/") + unique_string
);
960 BrowserThread::PostTask(
961 BrowserThread::DB
, FROM_HERE
,
962 base::Bind(base::IgnoreResult(&NativeBackendKWalletStub::AddLogin
),
963 base::Unretained(&backend
), form_google_
));
964 form_google_
.origin
=
965 GURL(std::string("http://www.google.com/") + unique_string_replacement
);
966 BrowserThread::PostTask(
967 BrowserThread::DB
, FROM_HERE
,
968 base::Bind(base::IgnoreResult(&NativeBackendKWalletStub::AddLogin
),
969 base::Unretained(&backend
), form_google_
));
972 // Read the raw value back. Change the |unique_string| to
973 // |unique_string_replacement| so the forms become unique.
974 TestKWallet::Blob value
;
975 ASSERT_TRUE(wallet_
.readEntry("Chrome Form Data (42)",
976 form_google_
.signon_realm
, &value
));
977 TestKWallet::Blob
sample(reinterpret_cast<const uint8_t*>(unique_string
));
978 size_t position
= value
.find(sample
);
979 ASSERT_NE(TestKWallet::Blob::npos
, position
);
980 value
.replace(position
, sample
.length(),
981 reinterpret_cast<const uint8_t*>(unique_string_replacement
));
982 wallet_
.writeEntry("Chrome Form Data (42)", form_google_
.signon_realm
, value
);
984 // Now test that GetAutofillableLogins returns only one form.
985 ScopedVector
<autofill::PasswordForm
> form_list
;
986 BrowserThread::PostTaskAndReplyWithResult(
987 BrowserThread::DB
, FROM_HERE
,
988 base::Bind(&NativeBackendKWalletStub::GetAutofillableLogins
,
989 base::Unretained(&backend
), &form_list
),
990 base::Bind(&CheckTrue
));
993 EXPECT_EQ(1u, form_list
.size());
994 EXPECT_EQ(form_google_
, *form_list
[0]);
996 std::vector
<const PasswordForm
*> forms
;
997 forms
.push_back(&form_google_
);
998 ExpectationArray expected
;
999 expected
.push_back(make_pair(std::string(form_google_
.signon_realm
), forms
));
1000 CheckPasswordForms("Chrome Form Data (42)", expected
);
1003 // TODO(mdm): add more basic tests here at some point.
1004 // (For example tests for storing >1 password per realm pickle.)
1006 class NativeBackendKWalletPickleTest
: public NativeBackendKWalletTestBase
{
1008 // Based on |form|, fills |pickle| with data conforming to
1009 // |effective_version|, but marking the pickle version as |stored_version|. In
1010 // most cases the two versions should be the same.
1011 void CreateVersion1PlusPickle(const PasswordForm
& form
,
1012 base::Pickle
* pickle
,
1014 int effective_version
);
1015 void CreateVersion0Pickle(bool size_32
,
1016 const PasswordForm
& form
,
1017 base::Pickle
* pickle
);
1018 // As explained in http://crbug.com/494229#c11, version 6 added a new optional
1019 // field to version 5. This field became required in version 7. Depending on
1020 // |with_optional_field|, this method checks deserialization with or without
1021 // the optional field.
1022 void CheckVersion6Pickle(bool with_optional_field
);
1023 void CheckVersion5Pickle();
1024 void CheckVersion3Pickle();
1025 void CheckVersion2Pickle();
1026 void CheckVersion1Pickle();
1027 void CheckVersion0Pickle(bool size_32
, PasswordForm::Scheme scheme
);
1030 // Creates a Pickle from |form|. If |size_32| is true, stores the number of
1031 // forms in the pickle as a 32bit uint, otherwise as 64 bit size_t. The latter
1032 // should be the case for versions > 0. If |date_created_internal| is true,
1033 // stores |date_created| as base::Time's internal value, otherwise as time_t.
1034 void CreatePickle(bool size_32
,
1035 bool date_created_internal
,
1036 const PasswordForm
& form
,
1037 base::Pickle
* pickle
);
1040 void NativeBackendKWalletPickleTest::CreateVersion1PlusPickle(
1041 const PasswordForm
& form
,
1042 base::Pickle
* pickle
,
1044 int effective_version
) {
1045 pickle
->WriteInt(stored_version
);
1046 CreatePickle(false, true, form
, pickle
);
1047 if (effective_version
< 2)
1049 pickle
->WriteInt(form
.type
);
1050 pickle
->WriteInt(form
.times_used
);
1051 autofill::SerializeFormData(form
.form_data
, pickle
);
1052 if (effective_version
< 3)
1054 pickle
->WriteInt64(form
.date_synced
.ToInternalValue());
1055 if (effective_version
< 4)
1057 pickle
->WriteString16(form
.display_name
);
1058 pickle
->WriteString(form
.icon_url
.spec());
1059 pickle
->WriteString(form
.federation_url
.spec());
1060 pickle
->WriteBool(form
.skip_zero_click
);
1061 if (effective_version
< 7)
1063 pickle
->WriteInt(form
.generation_upload_status
);
1066 void NativeBackendKWalletPickleTest::CreateVersion0Pickle(
1068 const PasswordForm
& form
,
1069 base::Pickle
* pickle
) {
1070 pickle
->WriteInt(0);
1071 CreatePickle(size_32
, false, form
, pickle
);
1074 void NativeBackendKWalletPickleTest::CreatePickle(bool size_32
,
1075 bool date_created_internal
,
1076 const PasswordForm
& form
,
1077 base::Pickle
* pickle
) {
1079 pickle
->WriteUInt32(1); // Size of form list. 32 bits.
1081 pickle
->WriteSizeT(1); // Size of form list. 64 bits.
1082 pickle
->WriteInt(form
.scheme
);
1083 pickle
->WriteString(form
.origin
.spec());
1084 pickle
->WriteString(form
.action
.spec());
1085 pickle
->WriteString16(form
.username_element
);
1086 pickle
->WriteString16(form
.username_value
);
1087 pickle
->WriteString16(form
.password_element
);
1088 pickle
->WriteString16(form
.password_value
);
1089 pickle
->WriteString16(form
.submit_element
);
1090 pickle
->WriteBool(form
.ssl_valid
);
1091 pickle
->WriteBool(form
.preferred
);
1092 pickle
->WriteBool(form
.blacklisted_by_user
);
1093 if (date_created_internal
)
1094 pickle
->WriteInt64(form
.date_created
.ToInternalValue());
1096 pickle
->WriteInt64(form
.date_created
.ToTimeT());
1099 void NativeBackendKWalletPickleTest::CheckVersion6Pickle(
1100 bool with_optional_field
) {
1101 base::Pickle pickle
;
1102 PasswordForm form
= form_google_
;
1103 if (!with_optional_field
) {
1104 PasswordForm default_values
;
1105 form
.generation_upload_status
= default_values
.generation_upload_status
;
1107 CreateVersion1PlusPickle(form
, &pickle
, 6, with_optional_field
? 7 : 5);
1109 ScopedVector
<PasswordForm
> form_list
=
1110 NativeBackendKWalletStub::DeserializeValue(form
.signon_realm
, pickle
);
1112 EXPECT_EQ(1u, form_list
.size());
1113 if (form_list
.size() > 0)
1114 CheckPasswordForm(form
, *form_list
[0], true);
1118 void NativeBackendKWalletPickleTest::CheckVersion5Pickle() {
1119 base::Pickle pickle
;
1120 PasswordForm default_values
;
1121 PasswordForm form
= form_google_
;
1122 // Remove the field which was not present in version #5.
1123 form
.generation_upload_status
= default_values
.generation_upload_status
;
1124 CreateVersion1PlusPickle(form
, &pickle
, 5, 5);
1126 ScopedVector
<PasswordForm
> form_list
=
1127 NativeBackendKWalletStub::DeserializeValue(form
.signon_realm
, pickle
);
1129 EXPECT_EQ(1u, form_list
.size());
1130 if (form_list
.size() > 0)
1131 CheckPasswordForm(form
, *form_list
[0], true);
1134 void NativeBackendKWalletPickleTest::CheckVersion3Pickle() {
1135 base::Pickle pickle
;
1136 PasswordForm default_values
;
1137 PasswordForm form
= form_google_
;
1138 // Remove the fields which were not present in version #3.
1139 form
.display_name
= default_values
.display_name
;
1140 form
.icon_url
= default_values
.icon_url
;
1141 form
.federation_url
= default_values
.federation_url
;
1142 form
.skip_zero_click
= default_values
.skip_zero_click
;
1143 form
.generation_upload_status
= default_values
.generation_upload_status
;
1144 CreateVersion1PlusPickle(form
, &pickle
, 3, 3);
1146 ScopedVector
<PasswordForm
> form_list
=
1147 NativeBackendKWalletStub::DeserializeValue(form
.signon_realm
, pickle
);
1149 EXPECT_EQ(1u, form_list
.size());
1150 if (form_list
.size() > 0)
1151 CheckPasswordForm(form
, *form_list
[0], false);
1154 void NativeBackendKWalletPickleTest::CheckVersion2Pickle() {
1155 base::Pickle pickle
;
1156 PasswordForm form
= old_form_google_
;
1157 form
.times_used
= form_google_
.times_used
;
1158 form
.type
= form_google_
.type
;
1159 form
.form_data
= form_google_
.form_data
;
1160 CreateVersion1PlusPickle(form
, &pickle
, 2, 2);
1162 ScopedVector
<PasswordForm
> form_list
=
1163 NativeBackendKWalletStub::DeserializeValue(form
.signon_realm
, pickle
);
1165 EXPECT_EQ(1u, form_list
.size());
1166 if (form_list
.size() > 0)
1167 CheckPasswordForm(form
, *form_list
[0], false);
1170 // Make sure that we can still read version 1 pickles.
1171 void NativeBackendKWalletPickleTest::CheckVersion1Pickle() {
1172 base::Pickle pickle
;
1173 PasswordForm form
= form_google_
;
1174 CreateVersion1PlusPickle(form
, &pickle
, 1, 1);
1176 ScopedVector
<autofill::PasswordForm
> form_list
=
1177 NativeBackendKWalletStub::DeserializeValue(form
.signon_realm
, pickle
);
1179 // This will match |old_form_google_| because not all the fields present in
1180 // |form_google_| will be deserialized.
1181 EXPECT_EQ(1u, form_list
.size());
1182 if (form_list
.size() > 0)
1183 CheckPasswordForm(old_form_google_
, *form_list
[0], false);
1186 void NativeBackendKWalletPickleTest::CheckVersion0Pickle(
1187 bool size_32
, PasswordForm::Scheme scheme
) {
1188 base::Pickle pickle
;
1189 PasswordForm form
= old_form_google_
;
1190 form
.scheme
= scheme
;
1191 CreateVersion0Pickle(size_32
, form
, &pickle
);
1192 ScopedVector
<autofill::PasswordForm
> form_list
=
1193 NativeBackendKWalletStub::DeserializeValue(form
.signon_realm
, pickle
);
1194 EXPECT_EQ(1u, form_list
.size());
1195 if (form_list
.size() > 0)
1196 CheckPasswordForm(form
, *form_list
[0], false);
1199 // Check that if KWallet fails to respond, the backend propagates the error.
1200 TEST_F(NativeBackendKWalletTest
, GetAllLoginsErrorHandling
) {
1201 NativeBackendKWalletStub
backend(42);
1202 EXPECT_TRUE(backend
.InitWithBus(mock_session_bus_
));
1203 // Make KWallet fail on calling readEntry.
1204 failing_methods_
.insert("readEntry");
1206 // Store some non-blacklisted logins to be potentially returned.
1207 BrowserThread::PostTaskAndReplyWithResult(
1208 BrowserThread::DB
, FROM_HERE
,
1209 base::Bind(&NativeBackendKWalletStub::AddLogin
,
1210 base::Unretained(&backend
), form_google_
),
1211 base::Bind(&CheckPasswordChanges
,
1212 PasswordStoreChangeList(1, PasswordStoreChange(
1213 PasswordStoreChange::ADD
, form_google_
))));
1215 // Verify that nothing is in fact returned, because KWallet fails to respond.
1216 ScopedVector
<autofill::PasswordForm
> form_list
;
1217 BrowserThread::PostTask(BrowserThread::DB
, FROM_HERE
,
1218 base::Bind(&CheckGetAutofillableLoginsFails
,
1219 base::Unretained(&backend
), &form_list
));
1221 EXPECT_EQ(0u, form_list
.size());
1224 // We try both SCHEME_HTML and SCHEME_BASIC since the scheme is stored right
1225 // after the size in the pickle, so it's what gets read as part of the count
1226 // when reading 32-bit pickles on 64-bit systems. SCHEME_HTML is 0 (so we'll
1227 // detect errors later) while SCHEME_BASIC is 1 (so we'll detect it then). We
1228 // try both 32-bit and 64-bit pickles since only one will be the "other" size
1229 // for whatever architecture we're running on, but we want to make sure we can
1230 // read all combinations in any event.
1232 TEST_F(NativeBackendKWalletPickleTest
, ReadsOld32BitHTMLPickles
) {
1233 CheckVersion0Pickle(true, PasswordForm::SCHEME_HTML
);
1236 TEST_F(NativeBackendKWalletPickleTest
, ReadsOld32BitHTTPPickles
) {
1237 CheckVersion0Pickle(true, PasswordForm::SCHEME_BASIC
);
1240 TEST_F(NativeBackendKWalletPickleTest
, ReadsOld64BitHTMLPickles
) {
1241 CheckVersion0Pickle(false, PasswordForm::SCHEME_HTML
);
1244 TEST_F(NativeBackendKWalletPickleTest
, ReadsOld64BitHTTPPickles
) {
1245 CheckVersion0Pickle(false, PasswordForm::SCHEME_BASIC
);
1248 TEST_F(NativeBackendKWalletPickleTest
, CheckVersion1Pickle
) {
1249 CheckVersion1Pickle();
1252 TEST_F(NativeBackendKWalletPickleTest
, CheckVersion2Pickle
) {
1253 CheckVersion2Pickle();
1256 TEST_F(NativeBackendKWalletPickleTest
, CheckVersion3Pickle
) {
1257 CheckVersion3Pickle();
1260 TEST_F(NativeBackendKWalletPickleTest
, CheckVersion5Pickle
) {
1261 CheckVersion5Pickle();
1264 TEST_F(NativeBackendKWalletPickleTest
, CheckVersion6Pickle
) {
1265 CheckVersion6Pickle(false);
1266 CheckVersion6Pickle(true);