Commit 085e76f6 authored by Jan Wilken Dörrie's avatar Jan Wilken Dörrie Committed by Commit Bot

[Passwords] Parse zxcvbn dicts in background

This change updates the zxcvbn data component and library to support
parsing the data dictionaries on the background thread.

Fixed: 1112461
Change-Id: I1b553bf448c1baf9b0a1359a853fc5360716e52a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2332609Reviewed-by: default avatarJoshua Pawlicki <waffles@chromium.org>
Commit-Queue: Jan Wilken Dörrie <jdoerrie@chromium.org>
Cr-Commit-Position: refs/heads/master@{#797629}
parent 45df86d3
......@@ -19,6 +19,7 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/scoped_refptr.h"
#include "base/strings/string_split.h"
#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
#include "base/util/ranges/algorithm.h"
......@@ -30,6 +31,7 @@
#include "components/update_client/update_client_errors.h"
#include "components/update_client/utils.h"
#include "third_party/zxcvbn-cpp/native-src/zxcvbn/frequency_lists.hpp"
#include "third_party/zxcvbn-cpp/native-src/zxcvbn/frequency_lists_common.hpp"
namespace component_updater {
......@@ -69,33 +71,27 @@ constexpr std::array<TagAndFileName, 6> kTagAndFileNamePairs = {{
ZxcvbnDataComponentInstallerPolicy::kUsTvAndFilmTxtFileName},
}};
using DictionaryMap = base::flat_map<zxcvbn::DictionaryTag, std::string>;
DictionaryMap ReadDictionaries(const base::FilePath& install_dir) {
DictionaryMap result;
result.reserve(kTagAndFileNamePairs.size());
using RankedDictionaries =
std::unordered_map<zxcvbn::DictionaryTag, zxcvbn::RankedDict>;
RankedDictionaries ParseRankedDictionaries(const base::FilePath& install_dir) {
RankedDictionaries result;
for (const auto& pair : kTagAndFileNamePairs) {
base::FilePath dictionary_path = install_dir.Append(pair.file_name);
DVLOG(1) << "Reading Dictionary from file: " << dictionary_path;
std::string dictionary;
if (base::ReadFileToString(dictionary_path, &dictionary))
result.try_emplace(result.end(), pair.tag, std::move(dictionary));
else
if (base::ReadFileToString(dictionary_path, &dictionary)) {
result.emplace(pair.tag, zxcvbn::build_ranked_dict(base::SplitStringPiece(
dictionary, "\r\n", base::TRIM_WHITESPACE,
base::SPLIT_WANT_NONEMPTY)));
} else {
VLOG(1) << "Failed reading from " << dictionary_path;
}
}
return result;
}
void ParseDictionaries(const DictionaryMap& dictionaries) {
for (const auto& pair : dictionaries) {
if (!zxcvbn::ParseRankedDictionary(pair.first, pair.second)) {
VLOG(1) << "Failed to parse dictionary for tag "
<< static_cast<int>(pair.first) << ". Contents: " << pair.second;
}
}
}
// The SHA256 of the SubjectPublicKeyInfo used to sign the extension.
// The extension id is: ojhpjlocmbogdgmfpkhlaaeamibhnphh
constexpr std::array<uint8_t, 32> kZxcvbnDataPublicKeySha256 = {
......@@ -141,8 +137,8 @@ void ZxcvbnDataComponentInstallerPolicy::ComponentReady(
base::ThreadPool::PostTaskAndReplyWithResult(
FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
base::BindOnce(&ReadDictionaries, install_dir),
base::BindOnce(&ParseDictionaries));
base::BindOnce(&ParseRankedDictionaries, install_dir),
base::BindOnce(&zxcvbn::SetRankedDicts));
}
base::FilePath ZxcvbnDataComponentInstallerPolicy::GetRelativeInstallDir()
......
......@@ -17,8 +17,8 @@ namespace component_updater {
namespace {
using ::testing::ElementsAre;
using ::testing::Pair;
using ::testing::UnorderedElementsAre;
} // namespace
......@@ -103,15 +103,15 @@ TEST_F(ZxcvbnDataComponentInstallerPolicyTest, ComponentReady) {
base::WriteFile(
GetPath().Append(
ZxcvbnDataComponentInstallerPolicy::kEnglishWikipediaTxtFileName),
"english_wikipedia");
"english\nwikipedia");
base::WriteFile(
GetPath().Append(
ZxcvbnDataComponentInstallerPolicy::kFemaleNamesTxtFileName),
"female_names");
"female\nnames");
base::WriteFile(
GetPath().Append(
ZxcvbnDataComponentInstallerPolicy::kMaleNamesTxtFileName),
"male_names");
"male\nnames");
base::WriteFile(
GetPath().Append(
ZxcvbnDataComponentInstallerPolicy::kPasswordsTxtFileName),
......@@ -122,26 +122,28 @@ TEST_F(ZxcvbnDataComponentInstallerPolicyTest, ComponentReady) {
base::WriteFile(
GetPath().Append(
ZxcvbnDataComponentInstallerPolicy::kUsTvAndFilmTxtFileName),
"us_tv_and_film");
"us\ntv\nand\nfilm");
policy().ComponentReady(version(), GetPath(), nullptr);
task_env().RunUntilIdle();
zxcvbn::RankedDicts ranked_dicts = zxcvbn::default_ranked_dicts();
EXPECT_THAT(zxcvbn::default_ranked_dicts(),
::testing::UnorderedElementsAre(
Pair(zxcvbn::DictionaryTag::ENGLISH_WIKIPEDIA,
ElementsAre(Pair("english_wikipedia", 1))),
Pair(zxcvbn::DictionaryTag::FEMALE_NAMES,
ElementsAre(Pair("female_names", 1))),
Pair(zxcvbn::DictionaryTag::MALE_NAMES,
ElementsAre(Pair("male_names", 1))),
Pair(zxcvbn::DictionaryTag::PASSWORDS,
ElementsAre(Pair("passwords", 1))),
Pair(zxcvbn::DictionaryTag::SURNAMES,
ElementsAre(Pair("surnames", 1))),
Pair(zxcvbn::DictionaryTag::US_TV_AND_FILM,
ElementsAre(Pair("us_tv_and_film", 1)))));
EXPECT_THAT(
zxcvbn::default_ranked_dicts(),
UnorderedElementsAre(
Pair(zxcvbn::DictionaryTag::ENGLISH_WIKIPEDIA,
UnorderedElementsAre(Pair("english", 1), Pair("wikipedia", 2))),
Pair(zxcvbn::DictionaryTag::FEMALE_NAMES,
UnorderedElementsAre(Pair("female", 1), Pair("names", 2))),
Pair(zxcvbn::DictionaryTag::MALE_NAMES,
UnorderedElementsAre(Pair("male", 1), Pair("names", 2))),
Pair(zxcvbn::DictionaryTag::PASSWORDS,
UnorderedElementsAre(Pair("passwords", 1))),
Pair(zxcvbn::DictionaryTag::SURNAMES,
UnorderedElementsAre(Pair("surnames", 1))),
Pair(zxcvbn::DictionaryTag::US_TV_AND_FILM,
UnorderedElementsAre(Pair("us", 1), Pair("tv", 2),
Pair("and", 3), Pair("film", 4)))));
}
} // namespace component_updater
#include <zxcvbn/frequency_lists.hpp>
#include <unordered_map>
#include <utility>
#include "base/no_destructor.h"
#include "base/strings/string_split.h"
#include "base/strings/string_piece.h"
namespace zxcvbn {
......@@ -16,16 +15,10 @@ std::unordered_map<DictionaryTag, RankedDict>& ranked_dicts() {
return *ranked_dicts;
}
}
bool ParseRankedDictionary(DictionaryTag tag, base::StringPiece str) {
RankedDict& dict = ranked_dicts()[tag];
if (!dict.empty())
return false;
} // namespace
dict = build_ranked_dict(base::SplitStringPiece(
str, "\r\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY));
return true;
void SetRankedDicts(std::unordered_map<DictionaryTag, RankedDict> dicts) {
ranked_dicts() = std::move(dicts);
}
RankedDicts convert_to_ranked_dicts(std::unordered_map<DictionaryTag, RankedDict> & ranked_dicts) {
......
......@@ -38,7 +38,7 @@ namespace zxcvbn {
using RankedDicts = std::unordered_map<DictionaryTag, const RankedDict &>;
bool ParseRankedDictionary(DictionaryTag tag, base::StringPiece str);
void SetRankedDicts(std::unordered_map<DictionaryTag, RankedDict> dicts);
RankedDicts convert_to_ranked_dicts(std::unordered_map<DictionaryTag, RankedDict> & ranked_dicts);
RankedDicts default_ranked_dicts();
......
diff --git a/third_party/zxcvbn-cpp/data-scripts/build_frequency_lists.py b/third_party/zxcvbn-cpp/data-scripts/build_frequency_lists.py
index d5504e073cb3..9be1391c5aa9 100755
index d5504e0..9be1391 100755
--- a/third_party/zxcvbn-cpp/data-scripts/build_frequency_lists.py
+++ b/third_party/zxcvbn-cpp/data-scripts/build_frequency_lists.py
@@ -122,8 +122,7 @@ def to_kv(lst, lst_name):
......@@ -37,20 +37,19 @@ index d5504e073cb3..9be1391c5aa9 100755
output_fn = output_coffee
diff --git a/third_party/zxcvbn-cpp/native-src/zxcvbn/frequency_lists.cpp b/third_party/zxcvbn-cpp/native-src/zxcvbn/frequency_lists.cpp
index 4e4b72756e34..17c73a67bd0a 100644
index 4e4b727..a7adbe9 100644
--- a/third_party/zxcvbn-cpp/native-src/zxcvbn/frequency_lists.cpp
+++ b/third_party/zxcvbn-cpp/native-src/zxcvbn/frequency_lists.cpp
@@ -1,11 +1,33 @@
@@ -1,11 +1,26 @@
#include <zxcvbn/frequency_lists.hpp>
-#include <zxcvbn/_frequency_lists.hpp>
-
#include <unordered_map>
+#include "base/no_destructor.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_piece.h"
+#include <utility>
+
+#include "base/no_destructor.h"
namespace zxcvbn {
+namespace {
......@@ -61,22 +60,16 @@ index 4e4b72756e34..17c73a67bd0a 100644
+ return *ranked_dicts;
+}
+
+}
+
+bool ParseRankedDictionary(DictionaryTag tag, base::StringPiece str) {
+ RankedDict& dict = ranked_dicts()[tag];
+ if (!dict.empty())
+ return false;
+} // namespace
+
+ dict = build_ranked_dict(base::SplitStringPiece(
+ str, "\r\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY));
+ return true;
+void SetRankedDicts(std::unordered_map<DictionaryTag, RankedDict> dicts) {
+ ranked_dicts() = std::move(dicts);
+}
+
RankedDicts convert_to_ranked_dicts(std::unordered_map<DictionaryTag, RankedDict> & ranked_dicts) {
RankedDicts build;
@@ -17,8 +39,7 @@ RankedDicts convert_to_ranked_dicts(std::unordered_map<DictionaryTag, RankedDict
@@ -17,8 +32,7 @@ RankedDicts convert_to_ranked_dicts(std::unordered_map<DictionaryTag, RankedDict
}
RankedDicts default_ranked_dicts() {
......@@ -87,10 +80,10 @@ index 4e4b72756e34..17c73a67bd0a 100644
-
}
diff --git a/third_party/zxcvbn-cpp/native-src/zxcvbn/frequency_lists.hpp b/third_party/zxcvbn-cpp/native-src/zxcvbn/frequency_lists.hpp
index c75ea30d5a91..191842fb530c 100644
index c75ea30..634ecb2 100644
--- a/third_party/zxcvbn-cpp/native-src/zxcvbn/frequency_lists.hpp
+++ b/third_party/zxcvbn-cpp/native-src/zxcvbn/frequency_lists.hpp
@@ -2,15 +2,24 @@
@@ -2,7 +2,6 @@
#define __ZXCVBN__FREQUENCY_LISTS_HPP
#include <zxcvbn/frequency_lists_common.hpp>
......@@ -98,10 +91,8 @@ index c75ea30d5a91..191842fb530c 100644
#include <unordered_map>
#include <cstdint>
@@ -10,7 +9,15 @@
+#include "base/strings/string_piece.h"
+
namespace zxcvbn {
-using DictionaryTag = _frequency_lists::DictionaryTag;
......@@ -117,11 +108,11 @@ index c75ea30d5a91..191842fb530c 100644
}
@@ -29,6 +38,8 @@ namespace zxcvbn {
@@ -29,6 +36,8 @@ namespace zxcvbn {
using RankedDicts = std::unordered_map<DictionaryTag, const RankedDict &>;
+bool ParseRankedDictionary(DictionaryTag tag, base::StringPiece str);
+void SetRankedDicts(std::unordered_map<DictionaryTag, RankedDict> dicts);
+
RankedDicts convert_to_ranked_dicts(std::unordered_map<DictionaryTag, RankedDict> & ranked_dicts);
RankedDicts default_ranked_dicts();
......
......@@ -304,7 +304,7 @@ TEST(ZxcvbnTest, DictionaryMatching) {
{
// default dictionaries
ParseRankedDictionary(DictionaryTag::US_TV_AND_FILM, "wow");
SetRankedDicts({{DictionaryTag::US_TV_AND_FILM, {{"wow", 1}}}});
std::vector<Match> matches =
dictionary_match("wow", default_ranked_dicts());
EXPECT_THAT(matches, ElementsAre(ExpectedDictionaryMatch{
......@@ -319,7 +319,7 @@ TEST(ZxcvbnTest, DictionaryMatching) {
{
// matches with provided user input dictionary
ParseRankedDictionary(DictionaryTag::USER_INPUTS, "foo\nbar");
SetRankedDicts({{DictionaryTag::USER_INPUTS, {{"foo", 1}, {"bar", 2}}}});
std::vector<Match> matches =
dictionary_match("foobar", default_ranked_dicts());
EXPECT_THAT(matches, ElementsAre(
......@@ -1004,7 +1004,8 @@ TEST(ZxcvbnTest, DateMatching) {
TEST(ZxcvbnTest, Omnimatch) {
EXPECT_THAT(omnimatch(""), IsEmpty());
ParseRankedDictionary(DictionaryTag::ENGLISH_WIKIPEDIA, "rosebud\nmaelstrom");
SetRankedDicts(
{{DictionaryTag::ENGLISH_WIKIPEDIA, {{"rosebud", 1}, {"maelstrom", 2}}}});
std::string password = "r0sebudmaelstrom11/20/91aaaa";
std::vector<Match> matches = omnimatch(password);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment