| OLD | NEW |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/safe_browsing/password_protection/password_protection_servi
ce.h" | 5 #include "components/safe_browsing/password_protection/password_protection_servi
ce.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/callback.h" | 8 #include "base/callback.h" |
| 9 #include "base/memory/ptr_util.h" | 9 #include "base/memory/ptr_util.h" |
| 10 #include "base/metrics/histogram_macros.h" | 10 #include "base/metrics/histogram_macros.h" |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 std::unique_ptr<base::DictionaryValue> verdict_dictionary = | 124 std::unique_ptr<base::DictionaryValue> verdict_dictionary = |
| 125 base::DictionaryValue::From(content_settings_->GetWebsiteSetting( | 125 base::DictionaryValue::From(content_settings_->GetWebsiteSetting( |
| 126 hostname, GURL(), CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION, | 126 hostname, GURL(), CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION, |
| 127 std::string(), nullptr)); | 127 std::string(), nullptr)); |
| 128 // Return early if there is no verdict cached for this origin. | 128 // Return early if there is no verdict cached for this origin. |
| 129 if (!verdict_dictionary.get() || verdict_dictionary->empty()) | 129 if (!verdict_dictionary.get() || verdict_dictionary->empty()) |
| 130 return LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED; | 130 return LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED; |
| 131 | 131 |
| 132 std::vector<std::string> paths; | 132 std::vector<std::string> paths; |
| 133 GeneratePathVariantsWithoutQuery(url, &paths); | 133 GeneratePathVariantsWithoutQuery(url, &paths); |
| 134 size_t max_path_depth = 0U; | 134 int max_path_depth = -1; |
| 135 LoginReputationClientResponse::VerdictType most_matching_verdict = | 135 LoginReputationClientResponse::VerdictType most_matching_verdict = |
| 136 LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED; | 136 LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED; |
| 137 // For all the verdicts of the same origin, we key them by |cache_expression|. | 137 // For all the verdicts of the same origin, we key them by |cache_expression|. |
| 138 // Its corresponding value is a DictionaryValue contains its creation time and | 138 // Its corresponding value is a DictionaryValue contains its creation time and |
| 139 // the serialized verdict proto. | 139 // the serialized verdict proto. |
| 140 for (base::DictionaryValue::Iterator it(*verdict_dictionary.get()); | 140 for (base::DictionaryValue::Iterator it(*verdict_dictionary.get()); |
| 141 !it.IsAtEnd(); it.Advance()) { | 141 !it.IsAtEnd(); it.Advance()) { |
| 142 base::DictionaryValue* verdict_entry = nullptr; | 142 base::DictionaryValue* verdict_entry = nullptr; |
| 143 CHECK(verdict_dictionary->GetDictionaryWithoutPathExpansion( | 143 CHECK(verdict_dictionary->GetDictionaryWithoutPathExpansion( |
| 144 it.key() /* cache_expression */, &verdict_entry)); | 144 it.key() /* cache_expression */, &verdict_entry)); |
| 145 int verdict_received_time; | 145 int verdict_received_time; |
| 146 LoginReputationClientResponse verdict; | 146 LoginReputationClientResponse verdict; |
| 147 CHECK(ParseVerdictEntry(verdict_entry, &verdict_received_time, &verdict)); | 147 CHECK(ParseVerdictEntry(verdict_entry, &verdict_received_time, &verdict)); |
| 148 // Since password protection content settings are keyed by origin, we only | 148 // Since password protection content settings are keyed by origin, we only |
| 149 // need to compare the path part of the cache_expression and the given url. | 149 // need to compare the path part of the cache_expression and the given url. |
| 150 std::string cache_expression_path = | 150 std::string cache_expression_path = |
| 151 GetCacheExpressionPath(verdict.cache_expression()); | 151 GetCacheExpressionPath(verdict.cache_expression()); |
| 152 | 152 |
| 153 if (verdict.cache_expression_exact_match()) { | 153 // Finds the most specific match. |
| 154 if (PathMatchCacheExpressionExactly(paths, cache_expression_path)) { | 154 int path_depth = static_cast<int>(GetPathDepth(cache_expression_path)); |
| 155 if (!IsCacheExpired(verdict_received_time, | 155 if (path_depth > max_path_depth && |
| 156 verdict.cache_duration_sec())) { | 156 PathVariantsMatchCacheExpression(paths, cache_expression_path)) { |
| 157 out_response->CopyFrom(verdict); | 157 max_path_depth = path_depth; |
| 158 return verdict.verdict_type(); | 158 // If the most matching verdict is expired, set the result to |
| 159 } else { // verdict expired | 159 // VERDICT_TYPE_UNSPECIFIED. |
| 160 return LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED; | 160 most_matching_verdict = |
| 161 } | 161 IsCacheExpired(verdict_received_time, verdict.cache_duration_sec()) |
| 162 } | 162 ? LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED |
| 163 } else { | 163 : verdict.verdict_type(); |
| 164 // If it doesn't require exact match, we need to find the most specific | 164 out_response->CopyFrom(verdict); |
| 165 // match. | |
| 166 size_t path_depth = GetPathDepth(cache_expression_path); | |
| 167 if (path_depth > max_path_depth && | |
| 168 PathVariantsMatchCacheExpression(paths, cache_expression_path) && | |
| 169 !IsCacheExpired(verdict_received_time, | |
| 170 verdict.cache_duration_sec())) { | |
| 171 max_path_depth = path_depth; | |
| 172 most_matching_verdict = verdict.verdict_type(); | |
| 173 out_response->CopyFrom(verdict); | |
| 174 } | |
| 175 } | 165 } |
| 176 } | 166 } |
| 177 return most_matching_verdict; | 167 return most_matching_verdict; |
| 178 } | 168 } |
| 179 | 169 |
| 180 void PasswordProtectionService::CacheVerdict( | 170 void PasswordProtectionService::CacheVerdict( |
| 181 const GURL& url, | 171 const GURL& url, |
| 182 LoginReputationClientResponse* verdict, | 172 LoginReputationClientResponse* verdict, |
| 183 const base::Time& receive_time) { | 173 const base::Time& receive_time) { |
| 184 DCHECK(verdict); | 174 DCHECK(verdict); |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 365 verdict_entry->Get(kVerdictProto, &binary_value); | 355 verdict_entry->Get(kVerdictProto, &binary_value); |
| 366 if (!result) | 356 if (!result) |
| 367 return false; | 357 return false; |
| 368 DCHECK(result); | 358 DCHECK(result); |
| 369 DCHECK_EQ(base::Value::Type::BINARY, binary_value->type()); | 359 DCHECK_EQ(base::Value::Type::BINARY, binary_value->type()); |
| 370 const auto blob = binary_value->GetBlob(); | 360 const auto blob = binary_value->GetBlob(); |
| 371 const std::string serialized_verdict_proto(blob.begin(), blob.end()); | 361 const std::string serialized_verdict_proto(blob.begin(), blob.end()); |
| 372 return out_verdict->ParseFromString(serialized_verdict_proto); | 362 return out_verdict->ParseFromString(serialized_verdict_proto); |
| 373 } | 363 } |
| 374 | 364 |
| 375 bool PasswordProtectionService::PathMatchCacheExpressionExactly( | |
| 376 const std::vector<std::string>& generated_paths, | |
| 377 const std::string& cache_expression_path) { | |
| 378 size_t cache_expression_path_depth = GetPathDepth(cache_expression_path); | |
| 379 if (generated_paths.size() <= cache_expression_path_depth) { | |
| 380 return false; | |
| 381 } | |
| 382 std::string canonical_path = generated_paths.back(); | |
| 383 size_t last_slash_pos = canonical_path.find_last_of("/"); | |
| 384 DCHECK_NE(std::string::npos, last_slash_pos); | |
| 385 return canonical_path.substr(0, last_slash_pos + 1) == cache_expression_path; | |
| 386 } | |
| 387 | |
| 388 bool PasswordProtectionService::PathVariantsMatchCacheExpression( | 365 bool PasswordProtectionService::PathVariantsMatchCacheExpression( |
| 389 const std::vector<std::string>& generated_paths, | 366 const std::vector<std::string>& generated_paths, |
| 390 const std::string& cache_expression_path) { | 367 const std::string& cache_expression_path) { |
| 391 for (const auto& path : generated_paths) { | 368 for (const auto& path : generated_paths) { |
| 392 if (cache_expression_path == path) { | 369 if (cache_expression_path == path) |
| 393 return true; | 370 return true; |
| 394 } | |
| 395 } | 371 } |
| 396 return false; | 372 return false; |
| 397 } | 373 } |
| 398 | 374 |
| 399 bool PasswordProtectionService::IsCacheExpired(int cache_creation_time, | 375 bool PasswordProtectionService::IsCacheExpired(int cache_creation_time, |
| 400 int cache_duration) { | 376 int cache_duration) { |
| 401 // TODO(jialiul): For now, we assume client's clock is accurate or almost | 377 // TODO(jialiul): For now, we assume client's clock is accurate or almost |
| 402 // accurate. Need some logic to handle cases where client's clock is way | 378 // accurate. Need some logic to handle cases where client's clock is way |
| 403 // off. | 379 // off. |
| 404 return base::Time::Now().ToDoubleT() > | 380 return base::Time::Now().ToDoubleT() > |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 448 const std::vector<char> verdict_blob(serialized_proto.begin(), | 424 const std::vector<char> verdict_blob(serialized_proto.begin(), |
| 449 serialized_proto.end()); | 425 serialized_proto.end()); |
| 450 std::unique_ptr<base::Value> binary_value = | 426 std::unique_ptr<base::Value> binary_value = |
| 451 base::MakeUnique<base::Value>(verdict_blob); | 427 base::MakeUnique<base::Value>(verdict_blob); |
| 452 DCHECK_EQ(base::Value::Type::BINARY, binary_value->type()); | 428 DCHECK_EQ(base::Value::Type::BINARY, binary_value->type()); |
| 453 result->Set(kVerdictProto, std::move(binary_value)); | 429 result->Set(kVerdictProto, std::move(binary_value)); |
| 454 return result; | 430 return result; |
| 455 } | 431 } |
| 456 | 432 |
| 457 } // namespace safe_browsing | 433 } // namespace safe_browsing |
| OLD | NEW |