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

Side by Side Diff: components/safe_browsing/password_protection/password_protection_service.cc

Issue 2773483003: Create PasswordProtectionRequest to handle password pings (Closed)
Patch Set: Add one more unittest Created 3 years, 9 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
OLDNEW
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"
11 #include "base/strings/string_number_conversions.h" 11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/string_split.h" 12 #include "base/strings/string_split.h"
13 #include "base/strings/string_util.h" 13 #include "base/strings/string_util.h"
14 #include "components/safe_browsing/password_protection/password_protection_reque st.h"
14 #include "components/safe_browsing_db/database_manager.h" 15 #include "components/safe_browsing_db/database_manager.h"
15 #include "components/safe_browsing_db/v4_protocol_manager_util.h" 16 #include "components/safe_browsing_db/v4_protocol_manager_util.h"
16 #include "content/public/browser/browser_thread.h" 17 #include "content/public/browser/browser_thread.h"
18 #include "google_apis/google_api_keys.h"
19 #include "net/base/escape.h"
17 20
18 using content::BrowserThread; 21 using content::BrowserThread;
19 22
20 namespace safe_browsing { 23 namespace safe_browsing {
21 24
22 namespace { 25 namespace {
23 26
24 // Keys for storing password protection verdict into a DictionaryValue. 27 // Keys for storing password protection verdict into a DictionaryValue.
25 static const char kCacheCreationTime[] = "cache_creation_time"; 28 const char kCacheCreationTime[] = "cache_creation_time";
26 static const char kVerdictProto[] = "verdict_proto"; 29 const char kVerdictProto[] = "verdict_proto";
30 const int kRequestTimeoutMs = 10000;
lpz 2017/03/24 15:40:48 general question: is there any benefit to tuning t
Jialiu Lin 2017/03/24 18:10:18 Acknowledged. We use constants for other SB pings.
31 const char kPasswordProtectionRequestUrl[] =
32 "https://sb-ssl.google.com/safebrowsing/clientreport/login";
27 33
28 // Helper function to determine if the given origin matches content settings 34 // Helper function to determine if the given origin matches content settings
29 // map's patterns. 35 // map's patterns.
30 bool OriginMatchPrimaryPattern( 36 bool OriginMatchPrimaryPattern(
31 const GURL& origin, 37 const GURL& origin,
32 const ContentSettingsPattern& primary_pattern, 38 const ContentSettingsPattern& primary_pattern,
33 const ContentSettingsPattern& secondary_pattern_unused) { 39 const ContentSettingsPattern& secondary_pattern_unused) {
34 return ContentSettingsPattern::FromURLNoWildcard(origin) == primary_pattern; 40 return ContentSettingsPattern::FromURLNoWildcard(origin) == primary_pattern;
35 } 41 }
36 42
(...skipping 11 matching lines...) Expand all
48 GURL GetHostNameWithHTTPScheme(const GURL& url) { 54 GURL GetHostNameWithHTTPScheme(const GURL& url) {
49 DCHECK(url.SchemeIsHTTPOrHTTPS()); 55 DCHECK(url.SchemeIsHTTPOrHTTPS());
50 std::string result(url::kHttpScheme); 56 std::string result(url::kHttpScheme);
51 result.append(url::kStandardSchemeSeparator).append(url.HostNoBrackets()); 57 result.append(url::kStandardSchemeSeparator).append(url.HostNoBrackets());
52 return GURL(result); 58 return GURL(result);
53 } 59 }
54 60
55 } // namespace 61 } // namespace
56 62
57 PasswordProtectionService::PasswordProtectionService( 63 PasswordProtectionService::PasswordProtectionService(
58 const scoped_refptr<SafeBrowsingDatabaseManager>& database_manager) 64 const scoped_refptr<SafeBrowsingDatabaseManager>& database_manager,
59 : database_manager_(database_manager), weak_factory_(this) { 65 scoped_refptr<net::URLRequestContextGetter> request_context_getter)
66 : request_context_getter_(request_context_getter),
67 database_manager_(database_manager),
68 weak_factory_(this) {
60 DCHECK_CURRENTLY_ON(BrowserThread::UI); 69 DCHECK_CURRENTLY_ON(BrowserThread::UI);
61 } 70 }
62 71
63 PasswordProtectionService::~PasswordProtectionService() { 72 PasswordProtectionService::~PasswordProtectionService() {
73 CancelPendingRequests();
64 weak_factory_.InvalidateWeakPtrs(); 74 weak_factory_.InvalidateWeakPtrs();
65 } 75 }
66 76
67 void PasswordProtectionService::RecordPasswordReuse(const GURL& url) { 77 void PasswordProtectionService::RecordPasswordReuse(const GURL& url) {
68 DCHECK_CURRENTLY_ON(BrowserThread::UI); 78 DCHECK_CURRENTLY_ON(BrowserThread::UI);
69 DCHECK(database_manager_); 79 DCHECK(database_manager_);
70 if (!url.is_valid()) 80 if (!url.is_valid())
71 return; 81 return;
72 82
73 BrowserThread::PostTaskAndReplyWithResult( 83 BrowserThread::PostTask(
74 BrowserThread::IO, FROM_HERE, 84 BrowserThread::IO, FROM_HERE,
75 base::Bind(&SafeBrowsingDatabaseManager::MatchCsdWhitelistUrl, 85 base::Bind(
76 database_manager_, url), 86 &PasswordProtectionService::CheckCsdWhitelistOnIOThread, GetWeakPtr(),
77 base::Bind(&PasswordProtectionService::OnMatchCsdWhiteListResult, 87 url,
78 GetWeakPtr())); 88 base::Bind(&PasswordProtectionService::OnMatchCsdWhiteListResult,
89 GetWeakPtr())));
90 }
91
92 void PasswordProtectionService::CheckCsdWhitelistOnIOThread(
93 const GURL& url,
94 const CheckCsdWhitelistCallback& callback) {
95 DCHECK_CURRENTLY_ON(BrowserThread::IO);
96 DCHECK(database_manager_);
97 bool check_result = database_manager_->MatchCsdWhitelistUrl(url);
98 DCHECK(callback);
99 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
100 base::Bind(callback, check_result));
79 } 101 }
80 102
81 LoginReputationClientResponse::VerdictType 103 LoginReputationClientResponse::VerdictType
82 PasswordProtectionService::GetCachedVerdict( 104 PasswordProtectionService::GetCachedVerdict(
83 const HostContentSettingsMap* settings, 105 const HostContentSettingsMap* settings,
84 const GURL& url) { 106 const GURL& url,
85 // TODO(jialiul): Add UMA metrics to track if verdict is available, not 107 LoginReputationClientResponse* out_response) {
86 // available, or expired.
87 DCHECK(settings); 108 DCHECK(settings);
88 if (!url.is_valid()) { 109 if (!url.is_valid()) {
89 return LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED; 110 return LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED;
90 } 111 }
91 112
92 GURL hostname = GetHostNameWithHTTPScheme(url); 113 GURL hostname = GetHostNameWithHTTPScheme(url);
93 std::unique_ptr<base::DictionaryValue> verdict_dictionary = 114 std::unique_ptr<base::DictionaryValue> verdict_dictionary =
94 base::DictionaryValue::From(settings->GetWebsiteSetting( 115 base::DictionaryValue::From(settings->GetWebsiteSetting(
95 hostname, GURL(), CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION, 116 hostname, GURL(), CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION,
96 std::string(), nullptr)); 117 std::string(), nullptr));
97 // Return early if there is no verdict cached for this origin. 118 // Return early if there is no verdict cached for this origin.
98 if (!verdict_dictionary.get() || verdict_dictionary->empty()) { 119 if (!verdict_dictionary.get() || verdict_dictionary->empty())
99 return LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED; 120 return LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED;
100 }
101 121
102 std::vector<std::string> paths; 122 std::vector<std::string> paths;
103 GeneratePathVariantsWithoutQuery(url, &paths); 123 GeneratePathVariantsWithoutQuery(url, &paths);
104 size_t max_path_depth = 0U; 124 size_t max_path_depth = 0U;
105 LoginReputationClientResponse::VerdictType most_matching_verdict = 125 LoginReputationClientResponse::VerdictType most_matching_verdict =
106 LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED; 126 LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED;
107 // For all the verdicts of the same origin, we key them by |cache_expression|. 127 // For all the verdicts of the same origin, we key them by |cache_expression|.
108 // Its corresponding value is a DictionaryValue contains its creation time and 128 // Its corresponding value is a DictionaryValue contains its creation time and
109 // the serialized verdict proto. 129 // the serialized verdict proto.
110 for (base::DictionaryValue::Iterator it(*verdict_dictionary.get()); 130 for (base::DictionaryValue::Iterator it(*verdict_dictionary.get());
111 !it.IsAtEnd(); it.Advance()) { 131 !it.IsAtEnd(); it.Advance()) {
112 base::DictionaryValue* verdict_entry = nullptr; 132 base::DictionaryValue* verdict_entry = nullptr;
113 CHECK(verdict_dictionary->GetDictionaryWithoutPathExpansion( 133 CHECK(verdict_dictionary->GetDictionaryWithoutPathExpansion(
114 it.key() /* cache_expression */, &verdict_entry)); 134 it.key() /* cache_expression */, &verdict_entry));
115 int verdict_received_time; 135 int verdict_received_time;
116 LoginReputationClientResponse verdict; 136 LoginReputationClientResponse verdict;
117 CHECK(ParseVerdictEntry(verdict_entry, &verdict_received_time, &verdict)); 137 CHECK(ParseVerdictEntry(verdict_entry, &verdict_received_time, &verdict));
118 // Since password protection content settings are keyed by origin, we only 138 // Since password protection content settings are keyed by origin, we only
119 // need to compare the path part of the cache_expression and the given url. 139 // need to compare the path part of the cache_expression and the given url.
120 std::string cache_expression_path = 140 std::string cache_expression_path =
121 GetCacheExpressionPath(verdict.cache_expression()); 141 GetCacheExpressionPath(verdict.cache_expression());
122 142
123 if (verdict.cache_expression_exact_match()) { 143 if (verdict.cache_expression_exact_match()) {
124 if (PathMatchCacheExpressionExactly(paths, cache_expression_path)) { 144 if (PathMatchCacheExpressionExactly(paths, cache_expression_path)) {
125 return IsCacheExpired(verdict_received_time, 145 if (!IsCacheExpired(verdict_received_time,
126 verdict.cache_duration_sec()) 146 verdict.cache_duration_sec())) {
127 ? LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED 147 out_response->CopyFrom(verdict);
128 : verdict.verdict_type(); 148 return verdict.verdict_type();
149 } else { // verdict expired
150 return LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED;
151 }
129 } 152 }
130 } else { 153 } else {
131 // If it doesn't require exact match, we need to fine the most specific 154 // If it doesn't require exact match, we need to find the most specific
132 // match. 155 // match.
133 size_t path_depth = GetPathDepth(cache_expression_path); 156 size_t path_depth = GetPathDepth(cache_expression_path);
134 if (path_depth > max_path_depth && 157 if (path_depth > max_path_depth &&
135 PathVariantsMatchCacheExpression(paths, cache_expression_path) && 158 PathVariantsMatchCacheExpression(paths, cache_expression_path) &&
136 !IsCacheExpired(verdict_received_time, 159 !IsCacheExpired(verdict_received_time,
137 verdict.cache_duration_sec())) { 160 verdict.cache_duration_sec())) {
138 max_path_depth = path_depth; 161 max_path_depth = path_depth;
139 most_matching_verdict = verdict.verdict_type(); 162 most_matching_verdict = verdict.verdict_type();
163 out_response->CopyFrom(verdict);
140 } 164 }
141 } 165 }
142 } 166 }
143 return most_matching_verdict; 167 return most_matching_verdict;
144 } 168 }
145 169
146 void PasswordProtectionService::CacheVerdict( 170 void PasswordProtectionService::CacheVerdict(
147 const GURL& url, 171 const GURL& url,
148 LoginReputationClientResponse* verdict, 172 LoginReputationClientResponse* verdict,
149 const base::Time& receive_time, 173 const base::Time& receive_time,
150 HostContentSettingsMap* settings) { 174 HostContentSettingsMap* settings) {
151 DCHECK(verdict); 175 DCHECK(verdict);
152 176
153 GURL hostname = GetHostNameWithHTTPScheme(url); 177 GURL hostname = GetHostNameWithHTTPScheme(url);
154 std::unique_ptr<base::DictionaryValue> verdict_dictionary = 178 std::unique_ptr<base::DictionaryValue> verdict_dictionary =
155 base::DictionaryValue::From(settings->GetWebsiteSetting( 179 base::DictionaryValue::From(settings->GetWebsiteSetting(
156 hostname, GURL(), CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION, 180 hostname, GURL(), CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION,
157 std::string(), nullptr)); 181 std::string(), nullptr));
158 182
159 if (!verdict_dictionary.get()) 183 if (!verdict_dictionary.get())
160 verdict_dictionary = base::MakeUnique<base::DictionaryValue>(); 184 verdict_dictionary = base::MakeUnique<base::DictionaryValue>();
161 185
162 std::unique_ptr<base::DictionaryValue> verdict_entry = 186 std::unique_ptr<base::DictionaryValue> verdict_entry =
163 CreateDictionaryFromVerdict(verdict, receive_time); 187 CreateDictionaryFromVerdict(verdict, receive_time);
188
189 // Increases stored verdict count if we haven't seen this its cache expression
lpz 2017/03/24 15:40:48 nit:-its
Jialiu Lin 2017/03/24 18:10:18 Done.
190 // before.
191 if (!verdict_dictionary->HasKey(verdict->cache_expression()))
192 stored_verdict_counts_[settings] = GetStoredVerdictCount() + 1U;
164 // If same cache_expression is already in this verdict_dictionary, we simply 193 // If same cache_expression is already in this verdict_dictionary, we simply
165 // override it. 194 // override it.
166 verdict_dictionary->SetWithoutPathExpansion(verdict->cache_expression(), 195 verdict_dictionary->SetWithoutPathExpansion(verdict->cache_expression(),
167 std::move(verdict_entry)); 196 std::move(verdict_entry));
168 settings->SetWebsiteSettingDefaultScope( 197 settings->SetWebsiteSettingDefaultScope(
169 hostname, GURL(), CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION, 198 hostname, GURL(), CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION,
170 std::string(), std::move(verdict_dictionary)); 199 std::string(), std::move(verdict_dictionary));
171 } 200 }
172 201
202 void PasswordProtectionService::StartRequest(
203 const GURL& main_frame_url,
204 LoginReputationClientRequest::TriggerType type,
205 bool is_extended_reporting,
206 bool is_incognito) {
207 DCHECK_CURRENTLY_ON(BrowserThread::UI);
208 std::unique_ptr<PasswordProtectionRequest> request =
209 base::MakeUnique<PasswordProtectionRequest>(
210 main_frame_url, type, is_extended_reporting, is_incognito,
211 GetWeakPtr(), GetRequestTimeoutInMS());
212 DCHECK(request);
213 request->Start();
214 requests_.insert(std::move(request));
215 }
216
217 void PasswordProtectionService::RequestFinished(
218 PasswordProtectionRequest* request,
219 std::unique_ptr<LoginReputationClientResponse> response) {
220 DCHECK_CURRENTLY_ON(BrowserThread::UI);
221
222 DCHECK(request);
223 // TODO(jialiul): We don't cache verdict for incognito mode for now.
224 // Later we may consider temporarily caching verdict.
225 if (!request->is_incognito() && response) {
226 CacheVerdict(request->main_frame_url(), response.get(), base::Time::Now(),
227 GetSettingMapForActiveProfile());
228 }
229 // Finished processing this request. Remove it from pending list.
230 for (auto it = requests_.begin(); it != requests_.end(); it++) {
231 if (it->get() == request) {
232 requests_.erase(it);
233 break;
234 }
235 }
236 }
237
238 void PasswordProtectionService::CancelPendingRequests() {
239 DCHECK_CURRENTLY_ON(BrowserThread::UI);
240 for (auto it = requests_.begin(); it != requests_.end();) {
241 // We need to advance the iterator before we cancel because canceling
242 // the request will invalidate it when RequestFinished is called.
243 PasswordProtectionRequest* request = it->get();
244 it++;
245 request->Cancel(false);
246 }
247 DCHECK(requests_.empty());
248 }
249
250 GURL PasswordProtectionService::GetPasswordProtectionRequestUrl() {
251 GURL url(kPasswordProtectionRequestUrl);
252 std::string api_key = google_apis::GetAPIKey();
253 DCHECK(!api_key.empty());
254 return url.Resolve("?key=" + net::EscapeQueryParamValue(api_key, true));
255 }
256
257 size_t PasswordProtectionService::GetStoredVerdictCount() {
258 HostContentSettingsMap* content_setting_map = GetSettingMapForActiveProfile();
259 DCHECK(content_setting_map);
260 auto it = stored_verdict_counts_.find(content_setting_map);
261 // If we have already computed this, return its value.
262 if (it != stored_verdict_counts_.end())
263 return it->second;
264
265 ContentSettingsForOneType password_protection_settings;
266 content_setting_map->GetSettingsForOneType(
267 CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION, std::string(),
268 &password_protection_settings);
269 stored_verdict_counts_[content_setting_map] = 0U;
270 if (password_protection_settings.empty())
271 return 0U;
272
273 for (const ContentSettingPatternSource& source :
274 password_protection_settings) {
275 std::unique_ptr<base::DictionaryValue> verdict_dictionary =
276 base::DictionaryValue::From(content_setting_map->GetWebsiteSetting(
277 GURL(source.primary_pattern.ToString()), GURL(),
278 CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION, std::string(), nullptr));
279 stored_verdict_counts_[content_setting_map] += verdict_dictionary->size();
280 }
281 return stored_verdict_counts_[content_setting_map];
282 }
283
284 int PasswordProtectionService::GetRequestTimeoutInMS() {
285 return kRequestTimeoutMs;
286 }
287
173 void PasswordProtectionService::OnMatchCsdWhiteListResult( 288 void PasswordProtectionService::OnMatchCsdWhiteListResult(
174 bool match_whitelist) { 289 bool match_whitelist) {
175 DCHECK_CURRENTLY_ON(BrowserThread::UI);
176 UMA_HISTOGRAM_BOOLEAN( 290 UMA_HISTOGRAM_BOOLEAN(
177 "PasswordManager.PasswordReuse.MainFrameMatchCsdWhitelist", 291 "PasswordManager.PasswordReuse.MainFrameMatchCsdWhitelist",
178 match_whitelist); 292 match_whitelist);
179 } 293 }
180 294
181 HostContentSettingsMap* 295 HostContentSettingsMap*
182 PasswordProtectionService::GetSettingMapForActiveProfile() { 296 PasswordProtectionService::GetSettingMapForActiveProfile() {
183 // TODO(jialiul): Make this a pure virtual function when we have a derived 297 // TODO(jialiul): Make this a pure virtual function when we have a derived
184 // class ready in chrome/browser/safe_browsing directory. 298 // class ready in chrome/browser/safe_browsing directory.
185 return nullptr; 299 return nullptr;
(...skipping 16 matching lines...) Expand all
202 } 316 }
203 317
204 void PasswordProtectionService::RemoveContentSettingsOnURLsDeleted( 318 void PasswordProtectionService::RemoveContentSettingsOnURLsDeleted(
205 bool all_history, 319 bool all_history,
206 const history::URLRows& deleted_rows, 320 const history::URLRows& deleted_rows,
207 HostContentSettingsMap* setting_map) { 321 HostContentSettingsMap* setting_map) {
208 DCHECK_CURRENTLY_ON(BrowserThread::UI); 322 DCHECK_CURRENTLY_ON(BrowserThread::UI);
209 if (all_history) { 323 if (all_history) {
210 setting_map->ClearSettingsForOneType( 324 setting_map->ClearSettingsForOneType(
211 CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION); 325 CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION);
326 stored_verdict_counts_[setting_map] = 0U;
212 return; 327 return;
213 } 328 }
214 329
215 // For now, if a URL is deleted from history, we simply remove all the 330 // For now, if a URL is deleted from history, we simply remove all the
216 // cached verdicts of the same origin. This is a pretty aggressive deletion. 331 // cached verdicts of the same origin. This is a pretty aggressive deletion.
217 // We might revisit this logic later to decide if we want to only delete the 332 // We might revisit this logic later to decide if we want to only delete the
218 // cached verdict whose cache expression matches this URL. 333 // cached verdict whose cache expression matches this URL.
219 for (const history::URLRow& row : deleted_rows) { 334 for (const history::URLRow& row : deleted_rows) {
335 GURL url_key = GetHostNameWithHTTPScheme(row.url());
336 std::unique_ptr<base::DictionaryValue> verdict_dictionary =
337 base::DictionaryValue::From(setting_map->GetWebsiteSetting(
338 url_key, GURL(), CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION,
339 std::string(), nullptr));
340 size_t verdict_cnt = verdict_dictionary->size();
lpz 2017/03/24 15:40:48 supernit: cnt->count
Jialiu Lin 2017/03/24 18:10:18 Done.
341 stored_verdict_counts_[setting_map] = GetStoredVerdictCount() - verdict_cnt;
220 setting_map->ClearSettingsForOneTypeWithPredicate( 342 setting_map->ClearSettingsForOneTypeWithPredicate(
221 CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION, 343 CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION,
222 base::Bind(&OriginMatchPrimaryPattern, row.url().GetOrigin())); 344 base::Bind(&OriginMatchPrimaryPattern, url_key));
223 } 345 }
224 } 346 }
225 347
226 // static 348 // static
227 bool PasswordProtectionService::ParseVerdictEntry( 349 bool PasswordProtectionService::ParseVerdictEntry(
228 base::DictionaryValue* verdict_entry, 350 base::DictionaryValue* verdict_entry,
229 int* out_verdict_received_time, 351 int* out_verdict_received_time,
230 LoginReputationClientResponse* out_verdict) { 352 LoginReputationClientResponse* out_verdict) {
231 base::Value* binary_value = nullptr; 353 base::Value* binary_value = nullptr;
232 bool result = verdict_entry && out_verdict && 354 bool result = verdict_entry && out_verdict &&
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 const std::vector<char> verdict_blob(serialized_proto.begin(), 440 const std::vector<char> verdict_blob(serialized_proto.begin(),
319 serialized_proto.end()); 441 serialized_proto.end());
320 std::unique_ptr<base::Value> binary_value = 442 std::unique_ptr<base::Value> binary_value =
321 base::MakeUnique<base::Value>(verdict_blob); 443 base::MakeUnique<base::Value>(verdict_blob);
322 DCHECK_EQ(base::Value::Type::BINARY, binary_value->type()); 444 DCHECK_EQ(base::Value::Type::BINARY, binary_value->type());
323 result->Set(kVerdictProto, std::move(binary_value)); 445 result->Set(kVerdictProto, std::move(binary_value));
324 return result; 446 return result;
325 } 447 }
326 448
327 } // namespace safe_browsing 449 } // namespace safe_browsing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698