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

Unified Diff: chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_config.cc

Issue 2614773008: Add a config class for the settings reset prompt. (Closed)
Patch Set: Created 3 years, 11 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_config.cc
diff --git a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_config.cc b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_config.cc
new file mode 100644
index 0000000000000000000000000000000000000000..54ac53fe74cc09d41452b7f906a6856000be5664
--- /dev/null
+++ b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_config.cc
@@ -0,0 +1,178 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_config.h"
+
+#include <utility>
+
+#include "base/json/json_reader.h"
+#include "base/memory/ptr_util.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/string_util.h"
+#include "base/values.h"
+#include "components/url_formatter/url_fixer.h"
+#include "components/variations/variations_associated_data.h"
+#include "crypto/sha2.h"
+#include "url/gurl.h"
+
+namespace safe_browsing {
+
+namespace {
+
+const char kSettingsResetPromptFeatureName[] = "SettingsResetPrompt";
+const char kDomainHashesParamName[] = "domain_hashes";
+const char kConfigErrorMetric[] = "SettingsResetPrompt.ConfigError";
+
+} // namespace.
+
+const base::Feature kSettingsResetPrompt{kSettingsResetPromptFeatureName,
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+// static
+bool SettingsResetPromptConfig::IsPromptEnabled() {
+ // TODO(alito): Add prefs to local state to track when the user was
+ // last prompted and ensure that we only prompt once per reset prompt
+ // wave.
+ return base::FeatureList::IsEnabled(kSettingsResetPrompt);
+}
+
+// static
+std::unique_ptr<SettingsResetPromptConfig> SettingsResetPromptConfig::Create() {
+ if (!IsPromptEnabled())
+ return nullptr;
+
+ auto prompt_config = base::WrapUnique(new SettingsResetPromptConfig());
+ if (!prompt_config->Init())
+ return nullptr;
+
+ return prompt_config;
+}
+
+SettingsResetPromptConfig::SettingsResetPromptConfig() {}
+
+SettingsResetPromptConfig::~SettingsResetPromptConfig() {}
+
+int SettingsResetPromptConfig::UrlToResetDomainId(const GURL& url) const {
+ DCHECK(IsPromptEnabled());
+
+ // Do a best-effort to fix the URL before testing if it is valid.
+ GURL fixed_url =
+ url_formatter::FixupURL(url.possibly_invalid_spec(), std::string());
+ if (!fixed_url.is_valid())
+ return -1;
+
+ // Try to match each sensible suffix of the URL host with the hashes
csharp 2017/01/09 21:54:59 Maybe worth mentioning why we want to try each suf
alito 2017/01/10 00:37:48 Done.
+ // in the prompt config. For example, if the host is
+ // "www.sub.domain.com", try hashes for for:
+ // "www.sub.domain.com"
+ // "sub.domain.com"
+ // "domain.com"
+ // "com"
+ SHA256Hash hash(crypto::kSHA256Length, '\0');
+ base::StringPiece host = fixed_url.host_piece();
+ while (!host.empty()) {
+ crypto::SHA256HashString(host, hash.data(), crypto::kSHA256Length);
+ auto iter = domain_hashes_.find(hash);
+ if (iter != domain_hashes_.end())
+ return iter->second;
+
+ size_t next_start_pos = host.find('.');
+ next_start_pos = next_start_pos == base::StringPiece::npos
+ ? base::StringPiece::npos
+ : next_start_pos + 1;
+ host = host.substr(next_start_pos);
+ }
+
+ return -1;
+}
+
+// Implements the hash function for SHA256Hash objects. Simply uses the
+// first bytes of the SHA256 hash as its own hash.
+size_t SettingsResetPromptConfig::SHA256HashHasher::operator()(
+ const SHA256Hash& key) const {
+ DCHECK_EQ(crypto::kSHA256Length, key.size());
+ // This is safe because |key| contains 32 bytes while a size_t is
+ // either 4 or 8 bytes.
+ return *reinterpret_cast<const size_t*>(key.data());
+}
+
+// These values are written to logs. New enum values can be added, but
+// existing enums must never be renumbered or deleted and reused. If you
+// do add values, also update the corresponding enum definition in the
+// histograms.xml file.
+enum SettingsResetPromptConfig::ConfigError : int {
+ CONFIG_ERROR_OK = 1,
csharp 2017/01/09 21:54:59 What about setting this to 0? (0 seem a bit more l
alito 2017/01/10 00:37:48 In general, I find reporting zero values to be a h
+ CONFIG_ERROR_MISSING_DOMAIN_HASHES_PARAM = 2,
+ CONFIG_ERROR_BAD_DOMAIN_HASHES_PARAM = 3,
+ CONFIG_ERROR_BAD_DOMAIN_HASH = 4,
+ CONFIG_ERROR_BAD_DOMAIN_ID = 5,
+ CONFIG_ERROR_DUPLICATE_DOMAIN_HASH = 6,
+ CONFIG_ERROR_MAX
+};
+
+bool SettingsResetPromptConfig::Init() {
+ if (!IsPromptEnabled())
+ return false;
+
+ std::string domain_hashes_json = variations::GetVariationParamValueByFeature(
+ kSettingsResetPrompt, kDomainHashesParamName);
+ ConfigError error = ParseDomainHashes(domain_hashes_json);
+ UMA_HISTOGRAM_ENUMERATION(kConfigErrorMetric, error, CONFIG_ERROR_MAX);
+ return error == CONFIG_ERROR_OK;
+}
+
+SettingsResetPromptConfig::ConfigError
+SettingsResetPromptConfig::ParseDomainHashes(
+ const std::string& domain_hashes_json) {
+ DCHECK(domain_hashes_.empty());
+
+ if (domain_hashes_json.empty())
+ return CONFIG_ERROR_MISSING_DOMAIN_HASHES_PARAM;
+
+ // Is the input parseable JSON?
+ std::unique_ptr<base::DictionaryValue> domains_dict =
+ base::DictionaryValue::From(base::JSONReader::Read(domain_hashes_json));
+ if (!domains_dict || domains_dict->empty())
+ return CONFIG_ERROR_BAD_DOMAIN_HASHES_PARAM;
+
+ // The input JSON should be a hash object with hex-encoded 32-byte
+ // hashes as keys and integer IDs as values. For example,
+ //
+ // {"2714..D7": "1", "2821..CB": "2", ...}
+ //
+ // Each key in the hash should be a 64-byte long string and each
+ // integer ID should fit in an int.
+ std::unordered_map<SHA256Hash, int, SHA256HashHasher> domain_hashes;
csharp 2017/01/09 21:54:59 What about just clearing domains_hashes_ here and
alito 2017/01/10 00:37:48 Done.
+ for (base::DictionaryValue::Iterator iter(*domains_dict); !iter.IsAtEnd();
+ iter.Advance()) {
+ std::string hash_string = iter.key();
csharp 2017/01/09 21:54:59 const std::string&?
alito 2017/01/10 00:37:48 Done.
+ if (hash_string.size() != crypto::kSHA256Length * 2)
+ return CONFIG_ERROR_BAD_DOMAIN_HASH;
+
+ // Convert hex-encoded hash string to its numeric value as bytes.
+ SHA256Hash hash;
+ hash.reserve(crypto::kSHA256Length);
+ if (!base::HexStringToBytes(hash_string, &hash))
+ return CONFIG_ERROR_BAD_DOMAIN_HASH;
+
+ // Convert the ID string to an integer.
+ std::string domain_id_string;
+ int domain_id;
+ if (!iter.value().GetAsString(&domain_id_string) ||
+ !base::StringToInt(domain_id_string, &domain_id)) {
+ return CONFIG_ERROR_BAD_DOMAIN_ID;
+ }
+
+ if (!domain_hashes.insert(std::make_pair(std::move(hash), domain_id))
+ .second)
+ return CONFIG_ERROR_DUPLICATE_DOMAIN_HASH;
+ }
+
+ domain_hashes_ = std::move(domain_hashes);
+ return CONFIG_ERROR_OK;
+}
+
+} // namespace safe_browsing.

Powered by Google App Engine
This is Rietveld 408576698