18
#include "TestBrowser.h"
20
#include "browser/BrowserMessageBuilder.h"
21
#include "browser/BrowserSettings.h"
22
#include "core/Group.h"
23
#include "core/Tools.h"
24
#include "crypto/Crypto.h"
29
#include <botan/sodium.h>
31
using namespace Botan::Sodium;
33
QTEST_GUILESS_MAIN(TestBrowser)
35
const QString PUBLICKEY = "UIIPObeoya1G8g1M5omgyoPR/j1mR1HlYHu0wHCgMhA=";
36
const QString SECRETKEY = "B8ei4ZjQJkWzZU2SK/tBsrYRwp+6ztEMf5GFQV+i0yI=";
37
const QString SERVERPUBLICKEY = "lKnbLhrVCOqzEjuNoUz1xj9EZlz8xeO4miZBvLrUPVQ=";
38
const QString SERVERSECRETKEY = "tbPQcghxfOgbmsnEqG2qMIj1W2+nh+lOJcNsHncaz1Q=";
39
const QString NONCE = "zBKdvTjL5bgWaKMCTut/8soM/uoMrFoZ";
40
const QString INCREMENTEDNONCE = "zRKdvTjL5bgWaKMCTut/8soM/uoMrFoZ";
41
const QString CLIENTID = "testClient";
43
void TestBrowser::initTestCase()
45
QVERIFY(Crypto::init());
46
m_browserService = browserService();
47
browserSettings()->setBestMatchOnly(false);
50
void TestBrowser::init()
52
m_browserAction.reset(new BrowserAction());
59
void TestBrowser::testChangePublicKeys()
62
json["action"] = "change-public-keys";
63
json["publicKey"] = PUBLICKEY;
64
json["nonce"] = NONCE;
66
auto response = m_browserAction->processClientMessage(nullptr, json);
67
QCOMPARE(response["action"].toString(), QString("change-public-keys"));
68
QCOMPARE(response["publicKey"].toString() == PUBLICKEY, false);
69
QCOMPARE(response["success"].toString(), TRUE_STR);
72
void TestBrowser::testEncryptMessage()
75
message["action"] = "test-action";
77
m_browserAction->m_publicKey = SERVERPUBLICKEY;
78
m_browserAction->m_secretKey = SERVERSECRETKEY;
79
m_browserAction->m_clientPublicKey = PUBLICKEY;
80
auto encrypted = browserMessageBuilder()->encryptMessage(message, NONCE, PUBLICKEY, SERVERSECRETKEY);
82
QCOMPARE(encrypted, QString("+zjtntnk4rGWSl/Ph7Vqip/swvgeupk4lNgHEm2OO3ujNr0OMz6eQtGwjtsj+/rP"));
85
void TestBrowser::testDecryptMessage()
87
QString message = "+zjtntnk4rGWSl/Ph7Vqip/swvgeupk4lNgHEm2OO3ujNr0OMz6eQtGwjtsj+/rP";
88
m_browserAction->m_publicKey = SERVERPUBLICKEY;
89
m_browserAction->m_secretKey = SERVERSECRETKEY;
90
m_browserAction->m_clientPublicKey = PUBLICKEY;
91
auto decrypted = browserMessageBuilder()->decryptMessage(message, NONCE, PUBLICKEY, SERVERSECRETKEY);
93
QCOMPARE(decrypted["action"].toString(), QString("test-action"));
96
void TestBrowser::testGetBase64FromKey()
98
unsigned char pk[crypto_box_PUBLICKEYBYTES];
100
for (unsigned int i = 0; i < crypto_box_PUBLICKEYBYTES; ++i) {
104
auto response = browserMessageBuilder()->getBase64FromKey(pk, crypto_box_PUBLICKEYBYTES);
105
QCOMPARE(response, QString("AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8="));
108
void TestBrowser::testIncrementNonce()
110
auto result = browserMessageBuilder()->incrementNonce(NONCE);
111
QCOMPARE(result, INCREMENTEDNONCE);
114
void TestBrowser::testBuildResponse()
116
const auto object = QJsonObject{{"test", true}};
117
const QJsonArray arr = {QJsonObject{{"test", true}}};
118
const auto val = QString("value1");
121
const Parameters params{
122
{"test-param-1", val}, {"test-param-2", 2}, {"test-param-3", false}, {"object", object}, {"arr", arr}};
124
const auto action = QString("test-action");
125
const auto message = browserMessageBuilder()->buildResponse(action, NONCE, params, PUBLICKEY, SERVERSECRETKEY);
126
QVERIFY(!message.isEmpty());
127
QCOMPARE(message["action"].toString(), action);
128
QCOMPARE(message["nonce"].toString(), NONCE);
130
const auto decrypted =
131
browserMessageBuilder()->decryptMessage(message["message"].toString(), NONCE, PUBLICKEY, SERVERSECRETKEY);
132
QVERIFY(!decrypted.isEmpty());
133
QCOMPARE(decrypted["test-param-1"].toString(), QString("value1"));
134
QCOMPARE(decrypted["test-param-2"].toInt(), 2);
135
QCOMPARE(decrypted["test-param-3"].toBool(), false);
137
const auto objectResult = decrypted["object"].toObject();
138
QCOMPARE(objectResult["test"].toBool(), true);
140
const auto arrResult = decrypted["arr"].toArray();
141
QCOMPARE(arrResult.size(), 1);
143
const auto firstArr = arrResult[0].toObject();
144
QCOMPARE(firstArr["test"].toBool(), true);
147
void TestBrowser::testSortPriority()
149
QFETCH(QString, entryUrl);
150
QFETCH(QString, siteUrl);
151
QFETCH(QString, formUrl);
152
QFETCH(int, expectedScore);
154
QScopedPointer<Entry> entry(new Entry());
155
entry->setUrl(entryUrl);
157
QCOMPARE(m_browserService->sortPriority(entry->getAllUrls(), siteUrl, formUrl), expectedScore);
160
void TestBrowser::testSortPriority_data()
162
const QString siteUrl = "https://github.com/login";
163
const QString formUrl = "https://github.com/session";
165
QTest::addColumn<QString>("entryUrl");
166
QTest::addColumn<QString>("siteUrl");
167
QTest::addColumn<QString>("formUrl");
168
QTest::addColumn<int>("expectedScore");
170
QTest::newRow("Exact Match") << siteUrl << siteUrl << siteUrl << 100;
171
QTest::newRow("Exact Match (site)") << siteUrl << siteUrl << formUrl << 100;
172
QTest::newRow("Exact Match (form)") << siteUrl << "https://github.net" << siteUrl << 100;
173
QTest::newRow("Exact Match No Trailing Slash") << "https://github.com"
174
<< "https://github.com/" << formUrl << 100;
175
QTest::newRow("Exact Match No Scheme") << "github.com/login" << siteUrl << formUrl << 100;
176
QTest::newRow("Exact Match with Query") << "https://github.com/login?test=test#fragment"
177
<< "https://github.com/login?test=test" << formUrl << 100;
179
QTest::newRow("Site Query Mismatch") << siteUrl << siteUrl + "?test=test" << formUrl << 90;
181
QTest::newRow("Path Mismatch (site)") << "https://github.com/" << siteUrl << formUrl << 85;
182
QTest::newRow("Path Mismatch (site) No Scheme") << "github.com" << siteUrl << formUrl << 85;
183
QTest::newRow("Path Mismatch (form)") << "https://github.com/"
184
<< "https://github.net" << formUrl << 85;
185
QTest::newRow("Path Mismatch (diff parent)") << "https://github.com/keepassxreboot" << siteUrl << formUrl << 80;
186
QTest::newRow("Path Mismatch (diff parent, form)") << "https://github.com/keepassxreboot"
187
<< "https://github.net" << formUrl << 70;
189
QTest::newRow("Subdomain Mismatch (site)") << siteUrl << "https://sub.github.com/"
190
<< "https://github.net/" << 60;
191
QTest::newRow("Subdomain Mismatch (form)") << siteUrl << "https://github.net/"
192
<< "https://sub.github.com/" << 50;
194
QTest::newRow("Scheme Mismatch") << "http://github.com" << siteUrl << formUrl << 0;
195
QTest::newRow("Scheme Mismatch w/path") << "http://github.com/login" << siteUrl << formUrl << 0;
196
QTest::newRow("Invalid URL") << "http://github" << siteUrl << formUrl << 0;
199
void TestBrowser::testSearchEntries()
201
auto db = QSharedPointer<Database>::create();
202
auto* root = db->rootGroup();
204
QStringList urls = {"https://github.com/login_page",
205
"https://github.com/login",
206
"https://github.com/",
209
"http://github.com/login",
215
createEntries(urls, root);
217
browserSettings()->setMatchUrlScheme(false);
219
m_browserService->searchEntries(db, "https://github.com", "https://github.com/session");
221
QCOMPARE(result.length(), 9);
222
QCOMPARE(result[0]->url(), QString("https://github.com/login_page"));
223
QCOMPARE(result[1]->url(), QString("https://github.com/login"));
224
QCOMPARE(result[2]->url(), QString("https://github.com/"));
225
QCOMPARE(result[3]->url(), QString("github.com/login"));
226
QCOMPARE(result[4]->url(), QString("http://github.com"));
227
QCOMPARE(result[5]->url(), QString("http://github.com/login"));
230
browserSettings()->setMatchUrlScheme(true);
231
result = m_browserService->searchEntries(db, "https://github.com", "https://github.com/session");
232
QCOMPARE(result.length(), 7);
233
QCOMPARE(result[0]->url(), QString("https://github.com/login_page"));
234
QCOMPARE(result[1]->url(), QString("https://github.com/login"));
235
QCOMPARE(result[2]->url(), QString("https://github.com/"));
236
QCOMPARE(result[3]->url(), QString("github.com/login"));
239
void TestBrowser::testSearchEntriesByPath()
241
auto db = QSharedPointer<Database>::create();
242
auto* root = db->rootGroup();
244
QStringList urlsRoot = {"https://root.example.com/", "root.example.com/login"};
245
auto entriesRoot = createEntries(urlsRoot, root);
247
auto* groupLevel1 = new Group();
248
groupLevel1->setParent(root);
249
groupLevel1->setName("TestGroup1");
250
QStringList urlsLevel1 = {"https://1.example.com/", "1.example.com/login"};
251
auto entriesLevel1 = createEntries(urlsLevel1, groupLevel1);
253
auto* groupLevel2 = new Group();
254
groupLevel2->setParent(groupLevel1);
255
groupLevel2->setName("TestGroup2");
256
QStringList urlsLevel2 = {"https://2.example.com/", "2.example.com/login"};
257
auto entriesLevel2 = createEntries(urlsLevel2, groupLevel2);
259
compareEntriesByPath(db, entriesRoot, "");
260
compareEntriesByPath(db, entriesLevel1, "TestGroup1/");
261
compareEntriesByPath(db, entriesLevel2, "TestGroup1/TestGroup2/");
264
void TestBrowser::compareEntriesByPath(QSharedPointer<Database> db, QList<Entry*> entries, QString path)
266
for (Entry* entry : entries) {
267
QString testUrl = "keepassxc://by-path/" + path + entry->title();
269
QCOMPARE(m_browserService->shouldIncludeEntry(entry, testUrl, ""), true);
270
auto result = m_browserService->searchEntries(db, testUrl, "");
271
QCOMPARE(result.length(), 1);
272
QCOMPARE(result[0], entry);
276
void TestBrowser::testSearchEntriesByUUID()
278
auto db = QSharedPointer<Database>::create();
279
auto* root = db->rootGroup();
282
QStringList urls = {"https://github.com/login_page",
283
"https://github.com/login",
284
"https://github.com/",
287
"http://github.com/login",
294
auto entries = createEntries(urls, root);
296
for (Entry* entry : entries) {
297
QString testUrl = "keepassxc://by-uuid/" + entry->uuidToHex();
299
QCOMPARE(m_browserService->shouldIncludeEntry(entry, testUrl, ""), true);
300
auto result = m_browserService->searchEntries(db, testUrl, "");
301
QCOMPARE(result.length(), 1);
302
QCOMPARE(result[0], entry);
306
QStringList uuids = {"00000000000000000000000000000000",
307
"00000000000000000000000000000001",
308
"00000000000000000000000000000002/",
310
"000000000000000000000000000000000000000"
311
"00000000000000000000000"};
313
for (QString uuid : uuids) {
314
QString testUrl = "keepassxc://by-uuid/" + uuid;
316
for (Entry* entry : entries) {
317
QCOMPARE(m_browserService->shouldIncludeEntry(entry, testUrl, ""), false);
320
auto result = m_browserService->searchEntries(db, testUrl, "");
321
QCOMPARE(result.length(), 0);
325
void TestBrowser::testSearchEntriesByReference()
327
auto db = QSharedPointer<Database>::create();
328
auto* root = db->rootGroup();
331
QStringList urls = {"https://subdomain.example.com",
333
"https://another.domain.com",
334
"https://subdomain.somesite.com",
337
"https://www.notincluded.com"};
338
auto entries = createEntries(urls, root);
340
auto firstEntryUuid = entries.first()->uuidToHex();
341
auto secondEntryUuid = entries[1]->uuidToHex();
342
auto fullReference = QString("{REF:A@I:%1}").arg(firstEntryUuid);
343
auto partialReference = QString("https://subdomain.{REF:A@I:%1}").arg(secondEntryUuid);
344
entries[2]->attributes()->set(EntryAttributes::AdditionalUrlAttribute, fullReference);
345
entries[3]->attributes()->set(EntryAttributes::AdditionalUrlAttribute, partialReference);
346
entries[4]->setUrl(fullReference);
347
entries[5]->setUrl(partialReference);
349
auto result = m_browserService->searchEntries(db, "https://subdomain.example.com", "");
350
QCOMPARE(result.length(), 6);
351
QCOMPARE(result[0]->url(), urls[0]);
352
QCOMPARE(result[1]->url(), urls[1]);
353
QCOMPARE(result[2]->url(), urls[2]);
355
result[2]->resolveMultiplePlaceholders(result[2]->attributes()->value(EntryAttributes::AdditionalUrlAttribute)),
357
QCOMPARE(result[3]->url(), urls[3]);
359
result[3]->resolveMultiplePlaceholders(result[3]->attributes()->value(EntryAttributes::AdditionalUrlAttribute)),
361
QCOMPARE(result[4]->url(), fullReference);
362
QCOMPARE(result[4]->resolveMultiplePlaceholders(result[4]->url()), urls[0]);
363
QCOMPARE(result[5]->url(), partialReference);
364
QCOMPARE(result[5]->resolveMultiplePlaceholders(result[5]->url()), urls[0]);
367
void TestBrowser::testSearchEntriesWithPort()
369
auto db = QSharedPointer<Database>::create();
370
auto* root = db->rootGroup();
372
QStringList urls = {"http://127.0.0.1:443", "http://127.0.0.1:80"};
374
createEntries(urls, root);
376
auto result = m_browserService->searchEntries(db, "http://127.0.0.1:443", "http://127.0.0.1");
377
QCOMPARE(result.length(), 1);
378
QCOMPARE(result[0]->url(), QString("http://127.0.0.1:443"));
381
void TestBrowser::testSearchEntriesWithAdditionalURLs()
383
auto db = QSharedPointer<Database>::create();
384
auto* root = db->rootGroup();
386
QStringList urls = {"https://github.com/", "https://www.example.com", "http://domain.com"};
388
auto entries = createEntries(urls, root);
391
entries.first()->attributes()->set(EntryAttributes::AdditionalUrlAttribute, "https://keepassxc.org");
393
auto result = m_browserService->searchEntries(db, "https://github.com", "https://github.com/session");
394
QCOMPARE(result.length(), 1);
395
QCOMPARE(result[0]->url(), QString("https://github.com/"));
398
auto additionalResult = m_browserService->searchEntries(db, "https://keepassxc.org", "https://keepassxc.org");
399
QCOMPARE(additionalResult.length(), 1);
400
QCOMPARE(additionalResult[0]->url(), QString("https://github.com/"));
403
void TestBrowser::testInvalidEntries()
405
auto db = QSharedPointer<Database>::create();
406
auto* root = db->rootGroup();
407
const QString url("https://github.com");
408
const QString submitUrl("https://github.com/session");
411
"https://github.com/login",
412
"https:///github.com/",
413
"http://github.com/**//*",
414
"http://*.github.com/login",
420
createEntries(urls, root);
422
browserSettings()->setMatchUrlScheme(true);
423
auto result = m_browserService->searchEntries(db, "https://github.com", "https://github.com/session");
424
QCOMPARE(result.length(), 2);
425
QCOMPARE(result[0]->url(), QString("https://github.com/login"));
426
QCOMPARE(result[1]->url(), QString("//github.com"));
429
QCOMPARE(m_browserService->handleURL(urls[0], url, submitUrl), true);
430
QCOMPARE(m_browserService->handleURL(urls[1], url, submitUrl), false);
431
QCOMPARE(m_browserService->handleURL(urls[2], url, submitUrl), false);
432
QCOMPARE(m_browserService->handleURL(urls[3], url, submitUrl), false);
433
QCOMPARE(m_browserService->handleURL(urls[4], url, submitUrl), true);
434
QCOMPARE(m_browserService->handleURL(urls[5], url, submitUrl), false);
437
void TestBrowser::testSubdomainsAndPaths()
439
auto db = QSharedPointer<Database>::create();
440
auto* root = db->rootGroup();
443
"https://www.github.com/login/page.xml",
444
"https://login.github.com/",
445
"https://github.com",
446
"http://www.github.com",
447
"http://login.github.com/pathtonowhere",
454
createEntries(urls, root);
456
browserSettings()->setMatchUrlScheme(false);
457
auto result = m_browserService->searchEntries(db, "https://github.com", "https://github.com/session");
458
QCOMPARE(result.length(), 1);
459
QCOMPARE(result[0]->url(), QString("https://github.com"));
462
result = m_browserService->searchEntries(db, "https://www.github.com", "https://www.github.com/session");
463
QCOMPARE(result.length(), 4);
464
QCOMPARE(result[0]->url(), QString("https://www.github.com/login/page.xml"));
465
QCOMPARE(result[1]->url(), QString("https://github.com"));
466
QCOMPARE(result[2]->url(), QString("http://www.github.com"));
467
QCOMPARE(result[3]->url(), QString("www.github.com/"));
470
root->setCustomDataTriState(BrowserService::OPTION_OMIT_WWW, Group::Enable);
471
result = m_browserService->searchEntries(db, "https://github.com", "https://github.com/session");
472
root->setCustomDataTriState(BrowserService::OPTION_OMIT_WWW, Group::Inherit);
473
QCOMPARE(result.length(), 4);
474
QCOMPARE(result[0]->url(), QString("https://www.github.com/login/page.xml"));
475
QCOMPARE(result[1]->url(), QString("https://github.com"));
476
QCOMPARE(result[2]->url(), QString("http://www.github.com"));
477
QCOMPARE(result[3]->url(), QString("www.github.com/"));
480
browserSettings()->setMatchUrlScheme(true);
481
result = m_browserService->searchEntries(db, "https://github.com", "https://github.com/session");
482
QCOMPARE(result.length(), 1);
483
QCOMPARE(result[0]->url(), QString("https://github.com"));
486
QStringList entryURLs = {
487
"https://accounts.example.com",
488
"https://accounts.example.com/path",
489
"https://subdomain.example.com/",
490
"https://another.accounts.example.com/",
491
"https://another.subdomain.example.com/",
492
"https://example.com/",
496
createEntries(entryURLs, root);
498
result = m_browserService->searchEntries(db, "https://accounts.example.com/", "https://accounts.example.com/");
499
QCOMPARE(result.length(), 3);
500
QCOMPARE(result[0]->url(), QString("https://accounts.example.com"));
501
QCOMPARE(result[1]->url(), QString("https://accounts.example.com/path"));
502
QCOMPARE(result[2]->url(), QString("https://example.com/"));
504
result = m_browserService->searchEntries(
505
db, "https://another.accounts.example.com/", "https://another.accounts.example.com/");
506
QCOMPARE(result.length(), 4);
507
QCOMPARE(result[0]->url(),
508
QString("https://accounts.example.com"));
509
QCOMPARE(result[1]->url(), QString("https://accounts.example.com/path"));
510
QCOMPARE(result[2]->url(), QString("https://another.accounts.example.com/"));
511
QCOMPARE(result[3]->url(), QString("https://example.com/"));
514
QStringList localFiles = {"file:///Users/testUser/tests/test.html"};
516
createEntries(localFiles, root);
519
result = m_browserService->searchEntries(db, "file://", "file:///Users/testUser/tests/test.html");
520
QCOMPARE(result.length(), 1);
523
QList<Entry*> TestBrowser::createEntries(QStringList& urls, Group* root) const
525
QList<Entry*> entries;
526
for (int i = 0; i < urls.length(); ++i) {
527
auto entry = new Entry();
528
entry->setGroup(root);
529
entry->beginUpdate();
530
entry->setUrl(urls[i]);
531
entry->setUsername(QString("User %1").arg(i));
532
entry->setUuid(QUuid::createUuid());
533
entry->setTitle(QString("Name_%1").arg(entry->uuidToHex()));
535
entries.push_back(entry);
541
void TestBrowser::testBestMatchingCredentials()
543
auto db = QSharedPointer<Database>::create();
544
auto* root = db->rootGroup();
547
QStringList urls = {"https://github.com/loginpage", "https://github.com/justsomepage", "https://github.com/"};
549
auto entries = createEntries(urls, root);
551
browserSettings()->setBestMatchOnly(true);
553
QString siteUrl = "https://github.com/loginpage";
554
auto result = m_browserService->searchEntries(db, siteUrl, siteUrl);
555
auto sorted = m_browserService->sortEntries(result, siteUrl, siteUrl);
556
QCOMPARE(sorted.size(), 1);
557
QCOMPARE(sorted[0]->url(), siteUrl);
559
siteUrl = "https://github.com/justsomepage";
560
result = m_browserService->searchEntries(db, siteUrl, siteUrl);
561
sorted = m_browserService->sortEntries(result, siteUrl, siteUrl);
562
QCOMPARE(sorted.size(), 1);
563
QCOMPARE(sorted[0]->url(), siteUrl);
565
siteUrl = "https://github.com/";
566
result = m_browserService->searchEntries(db, siteUrl, siteUrl);
567
sorted = m_browserService->sortEntries(entries, siteUrl, siteUrl);
568
QCOMPARE(sorted.size(), 1);
569
QCOMPARE(sorted[0]->url(), siteUrl);
572
browserSettings()->setBestMatchOnly(false);
573
siteUrl = "https://github.com/loginpage";
574
result = m_browserService->searchEntries(db, siteUrl, siteUrl);
575
sorted = m_browserService->sortEntries(result, siteUrl, siteUrl);
576
QCOMPARE(sorted.size(), 3);
577
QCOMPARE(sorted[0]->url(), siteUrl);
580
QStringList subdomainsUrls = {"https://sub.github.com/loginpage",
581
"https://sub.github.com/justsomepage",
582
"https://bus.github.com/justsomepage",
583
"https://subdomain.example.com/",
584
"https://subdomain.example.com",
585
"https://example.com"};
587
entries = createEntries(subdomainsUrls, root);
589
browserSettings()->setBestMatchOnly(true);
590
siteUrl = "https://sub.github.com/justsomepage";
591
result = m_browserService->searchEntries(db, siteUrl, siteUrl);
592
sorted = m_browserService->sortEntries(result, siteUrl, siteUrl);
593
QCOMPARE(sorted.size(), 1);
594
QCOMPARE(sorted[0]->url(), siteUrl);
596
siteUrl = "https://github.com/justsomepage";
597
result = m_browserService->searchEntries(db, siteUrl, siteUrl);
598
sorted = m_browserService->sortEntries(result, siteUrl, siteUrl);
599
QCOMPARE(sorted.size(), 1);
600
QCOMPARE(sorted[0]->url(), siteUrl);
602
siteUrl = "https://sub.github.com/justsomepage?wehavesomeextra=here";
603
result = m_browserService->searchEntries(db, siteUrl, siteUrl);
604
sorted = m_browserService->sortEntries(result, siteUrl, siteUrl);
605
QCOMPARE(sorted.size(), 1);
606
QCOMPARE(sorted[0]->url(), QString("https://sub.github.com/justsomepage"));
609
siteUrl = "https://subdomain.example.com/";
610
result = m_browserService->searchEntries(db, siteUrl, siteUrl);
611
sorted = m_browserService->sortEntries(result, siteUrl, siteUrl);
612
QCOMPARE(sorted.size(), 2);
613
QCOMPARE(sorted[0]->url(), QString("https://subdomain.example.com"));
614
QCOMPARE(sorted[1]->url(), QString("https://subdomain.example.com/"));
618
db = QSharedPointer<Database>::create();
619
root = db->rootGroup();
620
QStringList domainUrls = {"https://example.com", "https://example.com", "https://other.example.com"};
621
entries = createEntries(domainUrls, root);
622
siteUrl = "https://subdomain.example.com";
623
result = m_browserService->searchEntries(db, siteUrl, siteUrl);
624
sorted = m_browserService->sortEntries(result, siteUrl, siteUrl);
626
QCOMPARE(sorted.size(), 2);
627
QCOMPARE(sorted[0]->url(), QString("https://example.com"));
628
QCOMPARE(sorted[1]->url(), QString("https://example.com"));
631
db = QSharedPointer<Database>::create();
632
root = db->rootGroup();
633
QStringList fooUrls = {"https://example.com/foo", "https://example.com/bar"};
634
entries = createEntries(fooUrls, root);
636
for (const auto& url : fooUrls) {
637
result = m_browserService->searchEntries(db, url, url);
638
sorted = m_browserService->sortEntries(result, url, url);
639
QCOMPARE(sorted.size(), 1);
640
QCOMPARE(sorted[0]->url(), QString(url));
644
db = QSharedPointer<Database>::create();
645
root = db->rootGroup();
646
QStringList testUrls = {"http://some.domain.tld/somePath", "http://some.domain.tld/otherPath"};
647
entries = createEntries(testUrls, root);
649
for (const auto& url : testUrls) {
650
result = m_browserService->searchEntries(db, url, url);
651
sorted = m_browserService->sortEntries(result, url, url);
652
QCOMPARE(sorted.size(), 1);
653
QCOMPARE(sorted[0]->url(), QString(url));
657
void TestBrowser::testBestMatchingWithAdditionalURLs()
659
auto db = QSharedPointer<Database>::create();
660
auto* root = db->rootGroup();
662
QStringList urls = {"https://github.com/loginpage", "https://test.github.com/", "https://github.com/"};
664
auto entries = createEntries(urls, root);
665
browserSettings()->setBestMatchOnly(true);
668
entries.first()->attributes()->set(EntryAttributes::AdditionalUrlAttribute, "https://test.github.com/anotherpage");
671
auto result = m_browserService->searchEntries(
672
db, "https://test.github.com/anotherpage", "https://test.github.com/anotherpage");
673
auto sorted = m_browserService->sortEntries(
674
result, "https://test.github.com/anotherpage", "https://test.github.com/anotherpage");
675
QCOMPARE(sorted.length(), 1);
676
QCOMPARE(sorted[0]->url(), urls[0]);
679
void TestBrowser::testRestrictBrowserKey()
681
auto db = QSharedPointer<Database>::create();
682
auto* root = db->rootGroup();
685
QStringList urlsRoot = {"https://example.com/0"};
686
auto entriesRoot = createEntries(urlsRoot, root);
689
auto* group1 = new Group();
690
group1->setParent(root);
691
group1->setName("TestGroup1");
692
group1->customData()->set(BrowserService::OPTION_RESTRICT_KEY, "key1");
693
QStringList urls1 = {"https://example.com/1"};
694
auto entries1 = createEntries(urls1, group1);
697
auto* group2 = new Group();
698
group2->setParent(root);
699
group2->setName("TestGroup2");
700
group2->customData()->set(BrowserService::OPTION_RESTRICT_KEY, "key2");
701
QStringList urls2 = {"https://example.com/2"};
702
auto entries2 = createEntries(urls2, group2);
705
auto* group2b = new Group();
706
group2b->setParent(group2);
707
group2b->setName("TestGroup2b");
708
QStringList urls2b = {"https://example.com/2b"};
709
auto entries2b = createEntries(urls2b, group2b);
712
auto* group3 = new Group();
713
group3->setParent(root);
714
group3->setName("TestGroup3");
715
QStringList urls3 = {"https://example.com/3"};
716
auto entries3 = createEntries(urls3, group3);
719
auto siteUrl = QString("https://example.com");
720
auto result = m_browserService->searchEntries(db, siteUrl, siteUrl, {"key0"});
721
auto sorted = m_browserService->sortEntries(result, siteUrl, siteUrl);
722
QCOMPARE(sorted.size(), 2);
723
QCOMPARE(sorted[0]->url(), QString("https://example.com/3"));
724
QCOMPARE(sorted[1]->url(), QString("https://example.com/0"));
727
result = m_browserService->searchEntries(db, siteUrl, siteUrl, {"key1"});
728
sorted = m_browserService->sortEntries(result, siteUrl, siteUrl);
729
QCOMPARE(sorted.size(), 3);
730
QCOMPARE(sorted[0]->url(), QString("https://example.com/3"));
731
QCOMPARE(sorted[1]->url(), QString("https://example.com/1"));
732
QCOMPARE(sorted[2]->url(), QString("https://example.com/0"));
735
result = m_browserService->searchEntries(db, siteUrl, siteUrl, {"key2"});
736
sorted = m_browserService->sortEntries(result, siteUrl, siteUrl);
737
QCOMPARE(sorted.size(), 4);
738
QCOMPARE(sorted[0]->url(), QString("https://example.com/3"));
739
QCOMPARE(sorted[1]->url(), QString("https://example.com/2b"));
740
QCOMPARE(sorted[2]->url(), QString("https://example.com/2"));
741
QCOMPARE(sorted[3]->url(), QString("https://example.com/0"));