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

Side by Side Diff: chrome/browser/password_manager/native_backend_gnome_x_unittest.cc

Issue 7396013: Linux: revive a mysteriously disabled test and add tests for the GNOME Keyring native backend. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <stdarg.h>
6
7 #include "base/basictypes.h"
8 #include "base/stl_util-inl.h"
9 #include "base/string_util.h"
10 #include "base/time.h"
11 #include "base/utf_string_conversions.h"
12 #include "chrome/browser/password_manager/native_backend_gnome_x.h"
13 #include "chrome/browser/prefs/pref_service.h"
14 #include "chrome/common/pref_names.h"
15 #include "chrome/test/testing_profile.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 using webkit_glue::PasswordForm;
19
20 namespace {
21
22 // What follows is a very simple implementation of the subset of the GNOME
23 // Keyring API that we actually use. It gets substituted for the real one by
24 // MockGnomeKeyringLoader, which hooks into the facility normally used to load
25 // the GNOME Keyring library at runtime to avoid a static dependency on it.
26
27 struct MockKeyringItem {
28 MockKeyringItem() {}
29 MockKeyringItem(const char* keyring,
30 const std::string& display_name,
31 const std::string& password)
32 : keyring(keyring ? keyring : "login"),
33 display_name(display_name),
34 password(password) {}
35
36 struct ItemAttribute {
37 ItemAttribute() : type(UINT32), value_uint32(0) {}
38 explicit ItemAttribute(uint32_t value)
39 : type(UINT32), value_uint32(value) {}
40 explicit ItemAttribute(const std::string& value)
41 : type(STRING), value_string(value) {}
42
43 bool Equals(const ItemAttribute& x) const {
44 if (type != x.type) return false;
45 return (type == STRING) ? value_string == x.value_string
46 : value_uint32 == x.value_uint32;
47 }
48
49 enum { UINT32, STRING } type;
50 uint32_t value_uint32;
51 std::string value_string;
52 };
53
54 typedef std::map<std::string, ItemAttribute> attribute_map;
55 typedef std::vector<std::pair<std::string, ItemAttribute> > attribute_query;
56
57 bool Matches(const attribute_query& query) const {
58 // The real GNOME Keyring doesn't match empty queries.
59 if (query.empty()) return false;
60 for (size_t i = 0; i < query.size(); ++i) {
61 attribute_map::const_iterator match = attributes.find(query[i].first);
62 if (match == attributes.end()) return false;
63 if (!match->second.Equals(query[i].second)) return false;
64 }
65 return true;
66 }
67
68 std::string keyring;
69 std::string display_name;
70 std::string password;
71
72 attribute_map attributes;
73 };
74
75 // The list of all keyring items we have stored.
76 std::vector<MockKeyringItem> mock_keyring_items;
77 bool mock_keyring_reject_local_ids = false;
78
79 bool IsStringAttribute(const GnomeKeyringPasswordSchema* schema,
80 const std::string& name) {
81 for (size_t i = 0; schema->attributes[i].name; ++i)
82 if (name == schema->attributes[i].name)
83 return schema->attributes[i].type == GNOME_KEYRING_ATTRIBUTE_TYPE_STRING;
84 NOTREACHED() << "Requested type of nonexistent attribute";
85 return false;
86 }
87
88 gboolean mock_gnome_keyring_is_available() {
89 return true;
90 }
91
92 gpointer mock_gnome_keyring_store_password(
93 const GnomeKeyringPasswordSchema* schema,
94 const gchar* keyring,
95 const gchar* display_name,
96 const gchar* password,
97 GnomeKeyringOperationDoneCallback callback,
98 gpointer data,
99 GDestroyNotify destroy_data,
100 ...) {
101 mock_keyring_items.push_back(
102 MockKeyringItem(keyring, display_name, password));
103 MockKeyringItem* item = &mock_keyring_items.back();
104 const std::string keyring_desc = keyring ? StringPrintf("keyring %s", keyring)
105 : std::string("default keyring");
106 VLOG(1) << "Adding item with origin " << display_name
107 << " to " << keyring_desc;
108 va_list ap;
109 va_start(ap, destroy_data);
110 char* name;
111 while ((name = va_arg(ap, gchar*))) {
112 if (IsStringAttribute(schema, name)) {
113 item->attributes[name] =
114 MockKeyringItem::ItemAttribute(va_arg(ap, gchar*));
115 VLOG(1) << "Adding item attribute " << name
116 << ", value '" << item->attributes[name].value_string << "'";
117 } else {
118 item->attributes[name] =
119 MockKeyringItem::ItemAttribute(va_arg(ap, uint32_t));
120 VLOG(1) << "Adding item attribute " << name
121 << ", value " << item->attributes[name].value_uint32;
122 }
123 }
124 va_end(ap);
125 // As a hack to ease testing migration, make it possible to reject the new
126 // format for the app string. This way we can add them easily to migrate.
127 if (mock_keyring_reject_local_ids) {
128 MockKeyringItem::attribute_map::iterator it =
129 item->attributes.find("application");
130 if (it != item->attributes.end() &&
131 it->second.type == MockKeyringItem::ItemAttribute::STRING &&
132 base::StringPiece(it->second.value_string).starts_with("chrome-")) {
133 mock_keyring_items.pop_back();
134 // GnomeKeyringResult, data
135 callback(GNOME_KEYRING_RESULT_IO_ERROR, data);
136 return NULL;
137 }
138 }
139 // GnomeKeyringResult, data
140 callback(GNOME_KEYRING_RESULT_OK, data);
141 return NULL;
142 }
143
144 gpointer mock_gnome_keyring_delete_password(
145 const GnomeKeyringPasswordSchema* schema,
146 GnomeKeyringOperationDoneCallback callback,
147 gpointer data,
148 GDestroyNotify destroy_data,
149 ...) {
150 MockKeyringItem::attribute_query query;
151 va_list ap;
152 va_start(ap, destroy_data);
153 char* name;
154 while ((name = va_arg(ap, gchar*))) {
155 if (IsStringAttribute(schema, name)) {
156 query.push_back(make_pair(std::string(name),
157 MockKeyringItem::ItemAttribute(va_arg(ap, gchar*))));
158 VLOG(1) << "Querying with item attribute " << name
159 << ", value '" << query.back().second.value_string << "'";
160 } else {
161 query.push_back(make_pair(std::string(name),
162 MockKeyringItem::ItemAttribute(va_arg(ap, uint32_t))));
163 VLOG(1) << "Querying with item attribute " << name
164 << ", value " << query.back().second.value_uint32;
165 }
166 }
167 va_end(ap);
168 bool deleted = false;
169 for (size_t i = mock_keyring_items.size(); i > 0; --i) {
170 const MockKeyringItem* item = &mock_keyring_items[i - 1];
171 if (item->Matches(query)) {
172 VLOG(1) << "Deleting item with origin " << item->display_name;
173 mock_keyring_items.erase(mock_keyring_items.begin() + (i - 1));
174 deleted = true;
175 }
176 }
177 // GnomeKeyringResult, data
178 callback(deleted ? GNOME_KEYRING_RESULT_OK
179 : GNOME_KEYRING_RESULT_NO_MATCH, data);
180 return NULL;
181 }
182
183 gpointer mock_gnome_keyring_find_itemsv(
184 GnomeKeyringItemType type,
185 GnomeKeyringOperationGetListCallback callback,
186 gpointer data,
187 GDestroyNotify destroy_data,
188 ...) {
189 MockKeyringItem::attribute_query query;
190 va_list ap;
191 va_start(ap, destroy_data);
192 char* name;
193 while ((name = va_arg(ap, gchar*))) {
194 // Really a GnomeKeyringAttributeType, but promoted to int through ...
195 if (va_arg(ap, int) == GNOME_KEYRING_ATTRIBUTE_TYPE_STRING) {
196 query.push_back(make_pair(std::string(name),
197 MockKeyringItem::ItemAttribute(va_arg(ap, gchar*))));
198 VLOG(1) << "Querying with item attribute " << name
199 << ", value '" << query.back().second.value_string << "'";
200 } else {
201 query.push_back(make_pair(std::string(name),
202 MockKeyringItem::ItemAttribute(va_arg(ap, uint32_t))));
203 VLOG(1) << "Querying with item attribute " << name
204 << ", value " << query.back().second.value_uint32;
205 }
206 }
207 va_end(ap);
208 // Find matches and add them to a list of results.
209 GList* results = NULL;
210 for (size_t i = 0; i < mock_keyring_items.size(); ++i) {
211 const MockKeyringItem* item = &mock_keyring_items[i];
212 if (item->Matches(query)) {
213 GnomeKeyringFound* found = new GnomeKeyringFound;
214 found->keyring = strdup(item->keyring.c_str());
215 found->item_id = i;
216 found->attributes = gnome_keyring_attribute_list_new();
217 for (MockKeyringItem::attribute_map::const_iterator it =
218 item->attributes.begin();
219 it != item->attributes.end();
220 ++it) {
221 if (it->second.type == MockKeyringItem::ItemAttribute::STRING) {
222 gnome_keyring_attribute_list_append_string(
223 found->attributes, it->first.c_str(),
224 it->second.value_string.c_str());
225 } else {
226 gnome_keyring_attribute_list_append_uint32(
227 found->attributes, it->first.c_str(),
228 it->second.value_uint32);
229 }
230 }
231 found->secret = strdup(item->password.c_str());
232 results = g_list_prepend(results, found);
233 }
234 }
235 // GnomeKeyringResult, GList*, data
236 callback(results ? GNOME_KEYRING_RESULT_OK
237 : GNOME_KEYRING_RESULT_NO_MATCH, results, data);
238 // Now free the list of results.
239 GList* element = g_list_first(results);
240 while (element) {
241 GnomeKeyringFound* found = static_cast<GnomeKeyringFound*>(element->data);
242 free(found->keyring);
243 gnome_keyring_attribute_list_free(found->attributes);
244 free(found->secret);
245 element = g_list_next(element);
246 }
247 g_list_free(results);
248 return NULL;
249 }
250
251 const gchar* mock_gnome_keyring_result_to_message(GnomeKeyringResult res) {
252 return "mock keyring simulating failure";
253 }
254
255 // Inherit to get access to protected fields.
256 class MockGnomeKeyringLoader : public GnomeKeyringLoader {
257 public:
258 static bool LoadMockGnomeKeyring() {
259 #define GNOME_KEYRING_ASSIGN_POINTER(name) \
260 gnome_keyring_##name = &mock_gnome_keyring_##name;
261 GNOME_KEYRING_FOR_EACH_FUNC(GNOME_KEYRING_ASSIGN_POINTER)
262 #undef GNOME_KEYRING_ASSIGN_POINTER
263 keyring_loaded = true;
264 // Reset the state of the mock library.
265 mock_keyring_items.clear();
266 mock_keyring_reject_local_ids = false;
267 return true;
268 }
269 };
270
271 } // anonymous namespace
272
273 // NativeBackendGnome isn't reference counted, but in these unit tests that
274 // won't be a problem as it always outlives the threads we post tasks to.
275 template<>
276 struct RunnableMethodTraits<NativeBackendGnome> {
277 void RetainCallee(NativeBackendGnome*) {}
278 void ReleaseCallee(NativeBackendGnome*) {}
279 };
280
281 class NativeBackendGnomeTest : public testing::Test {
282 protected:
283 NativeBackendGnomeTest()
284 : ui_thread_(BrowserThread::UI, &message_loop_),
285 db_thread_(BrowserThread::DB) {
286 }
287
288 virtual void SetUp() {
289 ASSERT_TRUE(db_thread_.Start());
290
291 MockGnomeKeyringLoader::LoadMockGnomeKeyring();
292 profile_.reset(new TestingProfile());
293
294 form_google_.origin = GURL("http://www.google.com/");
295 form_google_.action = GURL("http://www.google.com/login");
296 form_google_.username_element = UTF8ToUTF16("user");
297 form_google_.username_value = UTF8ToUTF16("joeschmoe");
298 form_google_.password_element = UTF8ToUTF16("pass");
299 form_google_.password_value = UTF8ToUTF16("seekrit");
300 form_google_.submit_element = UTF8ToUTF16("submit");
301 form_google_.signon_realm = "Google";
302
303 form_isc_.origin = GURL("http://www.isc.org/");
304 form_isc_.action = GURL("http://www.isc.org/auth");
305 form_isc_.username_element = UTF8ToUTF16("id");
306 form_isc_.username_value = UTF8ToUTF16("janedoe");
307 form_isc_.password_element = UTF8ToUTF16("passwd");
308 form_isc_.password_value = UTF8ToUTF16("ihazabukkit");
309 form_isc_.submit_element = UTF8ToUTF16("login");
310 form_isc_.signon_realm = "ISC";
311 }
312
313 virtual void TearDown() {
314 MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask);
315 MessageLoop::current()->Run();
316 db_thread_.Stop();
317 }
318
319 void RunBothThreads() {
320 // First we post a message to the DB thread that will run after all other
321 // messages that have been posted to the DB thread (we don't expect more
322 // to be posted), which posts a message to the UI thread to quit the loop.
323 // That way we can run both loops and be sure that the UI thread loop will
324 // quit so we can get on with the rest of the test.
325 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
326 NewRunnableFunction(&PostQuitTask, &message_loop_));
327 MessageLoop::current()->Run();
328 }
329
330 static void PostQuitTask(MessageLoop* loop) {
331 loop->PostTask(FROM_HERE, new MessageLoop::QuitTask);
332 }
333
334 void CheckUint32Attribute(const MockKeyringItem* item,
335 const std::string& attribute,
336 uint32_t value) {
337 MockKeyringItem::attribute_map::const_iterator it =
338 item->attributes.find(attribute);
339 EXPECT_NE(item->attributes.end(), it);
340 if (it != item->attributes.end()) {
341 EXPECT_EQ(MockKeyringItem::ItemAttribute::UINT32, it->second.type);
342 EXPECT_EQ(value, it->second.value_uint32);
343 }
344 }
345
346 void CheckStringAttribute(const MockKeyringItem* item,
347 const std::string& attribute,
348 const std::string& value) {
349 MockKeyringItem::attribute_map::const_iterator it =
350 item->attributes.find(attribute);
351 EXPECT_NE(item->attributes.end(), it);
352 if (it != item->attributes.end()) {
353 EXPECT_EQ(MockKeyringItem::ItemAttribute::STRING, it->second.type);
354 EXPECT_EQ(value, it->second.value_string);
355 }
356 }
357
358 void CheckMockKeyringItem(const MockKeyringItem* item,
359 const PasswordForm& form,
360 const std::string& app_string) {
361 // We always add items to the login keyring.
362 EXPECT_EQ("login", item->keyring);
363 EXPECT_EQ(form.origin.spec(), item->display_name);
364 EXPECT_EQ(UTF16ToUTF8(form.password_value), item->password);
365 EXPECT_EQ(13u, item->attributes.size());
366 CheckStringAttribute(item, "origin_url", form.origin.spec());
367 CheckStringAttribute(item, "action_url", form.action.spec());
368 CheckStringAttribute(item, "username_element",
369 UTF16ToUTF8(form.username_element));
370 CheckStringAttribute(item, "username_value",
371 UTF16ToUTF8(form.username_value));
372 CheckStringAttribute(item, "password_element",
373 UTF16ToUTF8(form.password_element));
374 CheckStringAttribute(item, "submit_element",
375 UTF16ToUTF8(form.submit_element));
376 CheckStringAttribute(item, "signon_realm", form.signon_realm);
377 CheckUint32Attribute(item, "ssl_valid", form.ssl_valid);
378 CheckUint32Attribute(item, "preferred", form.preferred);
379 // We don't check the date created. It varies.
380 CheckUint32Attribute(item, "blacklisted_by_user", form.blacklisted_by_user);
381 CheckUint32Attribute(item, "scheme", form.scheme);
382 CheckStringAttribute(item, "application", app_string);
383 }
384
385 MessageLoopForUI message_loop_;
386 BrowserThread ui_thread_;
387 BrowserThread db_thread_;
388
389 scoped_ptr<TestingProfile> profile_;
390
391 // Provide some test forms to avoid having to set them up in each test.
392 PasswordForm form_google_;
393 PasswordForm form_isc_;
394 };
395
396 TEST_F(NativeBackendGnomeTest, BasicAddLogin) {
397 // Pretend that the migration has already taken place.
398 profile_->GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true);
399
400 NativeBackendGnome backend(42, profile_->GetPrefs());
401 backend.Init();
402
403 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
404 NewRunnableMethod(&backend,
405 &NativeBackendGnome::AddLogin,
406 form_google_));
407
408 RunBothThreads();
409
410 EXPECT_EQ(1u, mock_keyring_items.size());
411 if (mock_keyring_items.size() > 0)
412 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome-42");
413 }
414
415 TEST_F(NativeBackendGnomeTest, BasicListLogins) {
416 // Pretend that the migration has already taken place.
417 profile_->GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true);
418
419 NativeBackendGnome backend(42, profile_->GetPrefs());
420 backend.Init();
421
422 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
423 NewRunnableMethod(&backend,
424 &NativeBackendGnome::AddLogin,
425 form_google_));
426
427 std::vector<PasswordForm*> form_list;
428 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
429 NewRunnableMethod(&backend,
430 &NativeBackendGnome::GetAutofillableLogins,
431 &form_list));
432
433 RunBothThreads();
434
435 // Quick check that we got something back.
436 EXPECT_EQ(1u, form_list.size());
437 STLDeleteElements(&form_list);
438
439 EXPECT_EQ(1u, mock_keyring_items.size());
440 if (mock_keyring_items.size() > 0)
441 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome-42");
442 }
443
444 TEST_F(NativeBackendGnomeTest, BasicRemoveLogin) {
445 // Pretend that the migration has already taken place.
446 profile_->GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true);
447
448 NativeBackendGnome backend(42, profile_->GetPrefs());
449 backend.Init();
450
451 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
452 NewRunnableMethod(&backend,
453 &NativeBackendGnome::AddLogin,
454 form_google_));
455
456 RunBothThreads();
457
458 EXPECT_EQ(1u, mock_keyring_items.size());
459 if (mock_keyring_items.size() > 0)
460 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome-42");
461
462 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
463 NewRunnableMethod(&backend,
464 &NativeBackendGnome::RemoveLogin,
465 form_google_));
466
467 RunBothThreads();
468
469 EXPECT_EQ(0u, mock_keyring_items.size());
470 }
471
472 TEST_F(NativeBackendGnomeTest, RemoveNonexistentLogin) {
473 // Pretend that the migration has already taken place.
474 profile_->GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true);
475
476 NativeBackendGnome backend(42, profile_->GetPrefs());
477 backend.Init();
478
479 // First add an unrelated login.
480 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
481 NewRunnableMethod(&backend,
482 &NativeBackendGnome::AddLogin,
483 form_google_));
484
485 RunBothThreads();
486
487 EXPECT_EQ(1u, mock_keyring_items.size());
488 if (mock_keyring_items.size() > 0)
489 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome-42");
490
491 // Attempt to remove a login that doesn't exist.
492 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
493 NewRunnableMethod(&backend,
494 &NativeBackendGnome::RemoveLogin,
495 form_isc_));
496
497 // Make sure we can still get the first form back.
498 std::vector<PasswordForm*> form_list;
499 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
500 NewRunnableMethod(&backend,
501 &NativeBackendGnome::GetAutofillableLogins,
502 &form_list));
503
504 RunBothThreads();
505
506 // Quick check that we got something back.
507 EXPECT_EQ(1u, form_list.size());
508 STLDeleteElements(&form_list);
509
510 EXPECT_EQ(1u, mock_keyring_items.size());
511 if (mock_keyring_items.size() > 0)
512 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome-42");
513 }
514
515 TEST_F(NativeBackendGnomeTest, AddDuplicateLogin) {
516 // Pretend that the migration has already taken place.
517 profile_->GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true);
518
519 NativeBackendGnome backend(42, profile_->GetPrefs());
520 backend.Init();
521
522 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
523 NewRunnableMethod(&backend,
524 &NativeBackendGnome::AddLogin,
525 form_google_));
526 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
527 NewRunnableMethod(&backend,
528 &NativeBackendGnome::AddLogin,
529 form_google_));
530
531 RunBothThreads();
532
533 EXPECT_EQ(1u, mock_keyring_items.size());
534 if (mock_keyring_items.size() > 0)
535 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome-42");
536 }
537
538 // TODO(mdm): add more basic (i.e. non-migration) tests here at some point.
539
540 TEST_F(NativeBackendGnomeTest, MigrateOneLogin) {
541 // Reject attempts to migrate so we can populate the store.
542 mock_keyring_reject_local_ids = true;
543
544 {
545 NativeBackendGnome backend(42, profile_->GetPrefs());
546 backend.Init();
547
548 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
549 NewRunnableMethod(&backend,
550 &NativeBackendGnome::AddLogin,
551 form_google_));
552
553 // Make sure we can get the form back even when migration is failing.
554 std::vector<PasswordForm*> form_list;
555 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
556 NewRunnableMethod(&backend,
557 &NativeBackendGnome::GetAutofillableLogins,
558 &form_list));
559
560 RunBothThreads();
561
562 // Quick check that we got something back.
563 EXPECT_EQ(1u, form_list.size());
564 STLDeleteElements(&form_list);
565 }
566
567 EXPECT_EQ(1u, mock_keyring_items.size());
568 if (mock_keyring_items.size() > 0)
569 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome");
570
571 // Now allow the migration.
572 mock_keyring_reject_local_ids = false;
573
574 {
575 NativeBackendGnome backend(42, profile_->GetPrefs());
576 backend.Init();
577
578 // This should not trigger migration because there will be no results.
579 std::vector<PasswordForm*> form_list;
580 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
581 NewRunnableMethod(&backend,
582 &NativeBackendGnome::GetBlacklistLogins,
583 &form_list));
584
585 RunBothThreads();
586
587 // Check that we got nothing back.
588 EXPECT_EQ(0u, form_list.size());
589 STLDeleteElements(&form_list);
590 }
591
592 // Check that the keyring is unmodified.
593 EXPECT_EQ(1u, mock_keyring_items.size());
594 if (mock_keyring_items.size() > 0)
595 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome");
596
597 // Check that we haven't set the persistent preference.
598 EXPECT_FALSE(
599 profile_->GetPrefs()->GetBoolean(prefs::kPasswordsUseLocalProfileId));
600
601 {
602 NativeBackendGnome backend(42, profile_->GetPrefs());
603 backend.Init();
604
605 // Trigger the migration by looking something up.
606 std::vector<PasswordForm*> form_list;
607 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
608 NewRunnableMethod(&backend,
609 &NativeBackendGnome::GetAutofillableLogins,
610 &form_list));
611
612 RunBothThreads();
613
614 // Quick check that we got something back.
615 EXPECT_EQ(1u, form_list.size());
616 STLDeleteElements(&form_list);
617 }
618
619 EXPECT_EQ(2u, mock_keyring_items.size());
620 if (mock_keyring_items.size() > 0)
621 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome");
622 if (mock_keyring_items.size() > 1)
623 CheckMockKeyringItem(&mock_keyring_items[1], form_google_, "chrome-42");
624
625 // Check that we have set the persistent preference.
626 EXPECT_TRUE(
627 profile_->GetPrefs()->GetBoolean(prefs::kPasswordsUseLocalProfileId));
628 }
629
630 TEST_F(NativeBackendGnomeTest, MigrateToMultipleProfiles) {
631 // Reject attempts to migrate so we can populate the store.
632 mock_keyring_reject_local_ids = true;
633
634 {
635 NativeBackendGnome backend(42, profile_->GetPrefs());
636 backend.Init();
637
638 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
639 NewRunnableMethod(&backend,
640 &NativeBackendGnome::AddLogin,
641 form_google_));
642
643 RunBothThreads();
644 }
645
646 EXPECT_EQ(1u, mock_keyring_items.size());
647 if (mock_keyring_items.size() > 0)
648 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome");
649
650 // Now allow the migration.
651 mock_keyring_reject_local_ids = false;
652
653 {
654 NativeBackendGnome backend(42, profile_->GetPrefs());
655 backend.Init();
656
657 // Trigger the migration by looking something up.
658 std::vector<PasswordForm*> form_list;
659 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
660 NewRunnableMethod(&backend,
661 &NativeBackendGnome::GetAutofillableLogins,
662 &form_list));
663
664 RunBothThreads();
665
666 // Quick check that we got something back.
667 EXPECT_EQ(1u, form_list.size());
668 STLDeleteElements(&form_list);
669 }
670
671 EXPECT_EQ(2u, mock_keyring_items.size());
672 if (mock_keyring_items.size() > 0)
673 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome");
674 if (mock_keyring_items.size() > 1)
675 CheckMockKeyringItem(&mock_keyring_items[1], form_google_, "chrome-42");
676
677 // Check that we have set the persistent preference.
678 EXPECT_TRUE(
679 profile_->GetPrefs()->GetBoolean(prefs::kPasswordsUseLocalProfileId));
680
681 // Normally we'd actually have a different profile. But in the test just reset
682 // the profile's persistent pref; we pass in the local profile id anyway.
683 profile_->GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, false);
684
685 {
686 NativeBackendGnome backend(24, profile_->GetPrefs());
687 backend.Init();
688
689 // Trigger the migration by looking something up.
690 std::vector<PasswordForm*> form_list;
691 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
692 NewRunnableMethod(&backend,
693 &NativeBackendGnome::GetAutofillableLogins,
694 &form_list));
695
696 RunBothThreads();
697
698 // Quick check that we got something back.
699 EXPECT_EQ(1u, form_list.size());
700 STLDeleteElements(&form_list);
701 }
702
703 EXPECT_EQ(3u, mock_keyring_items.size());
704 if (mock_keyring_items.size() > 0)
705 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome");
706 if (mock_keyring_items.size() > 1)
707 CheckMockKeyringItem(&mock_keyring_items[1], form_google_, "chrome-42");
708 if (mock_keyring_items.size() > 2)
709 CheckMockKeyringItem(&mock_keyring_items[2], form_google_, "chrome-24");
710 }
711
712 TEST_F(NativeBackendGnomeTest, NoMigrationWithPrefSet) {
713 // Reject attempts to migrate so we can populate the store.
714 mock_keyring_reject_local_ids = true;
715
716 {
717 NativeBackendGnome backend(42, profile_->GetPrefs());
718 backend.Init();
719
720 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
721 NewRunnableMethod(&backend,
722 &NativeBackendGnome::AddLogin,
723 form_google_));
724
725 RunBothThreads();
726 }
727
728 EXPECT_EQ(1u, mock_keyring_items.size());
729 if (mock_keyring_items.size() > 0)
730 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome");
731
732 // Now allow migration, but also pretend that the it has already taken place.
733 mock_keyring_reject_local_ids = false;
734 profile_->GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true);
735
736 {
737 NativeBackendGnome backend(42, profile_->GetPrefs());
738 backend.Init();
739
740 // Trigger the migration by adding a new login.
741 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
742 NewRunnableMethod(&backend,
743 &NativeBackendGnome::AddLogin,
744 form_isc_));
745
746 // Look up all logins; we expect only the one we added.
747 std::vector<PasswordForm*> form_list;
748 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
749 NewRunnableMethod(&backend,
750 &NativeBackendGnome::GetAutofillableLogins,
751 &form_list));
752
753 RunBothThreads();
754
755 // Quick check that we got the right thing back.
756 EXPECT_EQ(1u, form_list.size());
757 if (form_list.size() > 0)
758 EXPECT_EQ(form_isc_.signon_realm, form_list[0]->signon_realm);
759 STLDeleteElements(&form_list);
760 }
761
762 EXPECT_EQ(2u, mock_keyring_items.size());
763 if (mock_keyring_items.size() > 0)
764 CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome");
765 if (mock_keyring_items.size() > 1)
766 CheckMockKeyringItem(&mock_keyring_items[1], form_isc_, "chrome-42");
767 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698