1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
|
// Copyright (c) 2010 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.
#ifndef CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_DATABASE_H_
#define CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_DATABASE_H_
#pragma once
#include <set>
#include <vector>
#include "base/file_path.h"
#include "base/lock.h"
#include "base/scoped_ptr.h"
#include "base/task.h"
#include "chrome/browser/safe_browsing/safe_browsing_store.h"
#include "chrome/browser/safe_browsing/safe_browsing_util.h"
#include "testing/gtest/include/gtest/gtest_prod.h"
namespace base {
class Time;
}
class BloomFilter;
class GURL;
class MessageLoop;
// Encapsulates the database that stores information about phishing
// and malware sites. There is one on-disk database for all profiles,
// as it doesn't contain user-specific data. This object is not
// thread-safe, i.e. all its methods should be used on the same thread
// that it was created on.
class SafeBrowsingDatabase {
public:
// Factory method for obtaining a SafeBrowsingDatabase implementation.
static SafeBrowsingDatabase* Create();
virtual ~SafeBrowsingDatabase();
// Initializes the database with the given filename.
virtual void Init(const FilePath& filename) = 0;
// Deletes the current database and creates a new one.
virtual bool ResetDatabase() = 0;
// Returns false if |url| is not in the database. If it returns
// true, then either |matching_list| is the name of the matching
// list, or |prefix_hits| and |full_hits| contains the matching hash
// prefixes. This function is safe to call from threads other than
// the creation thread.
virtual bool ContainsUrl(const GURL& url,
std::string* matching_list,
std::vector<SBPrefix>* prefix_hits,
std::vector<SBFullHashResult>* full_hits,
base::Time last_update) = 0;
// A database transaction should look like:
//
// std::vector<SBListChunkRanges> lists;
// if (db.UpdateStarted(&lists)) {
// // Do something with |lists|.
//
// // Process add/sub commands.
// db.InsertChunks(list_name, chunks);
//
// // Process adddel/subdel commands.
// db.DeleteChunks(chunks_deletes);
//
// // If passed true, processes the collected chunk info and
// // rebuilds the bloom filter. If passed false, rolls everything
// // back.
// db.UpdateFinished(success);
// }
//
// If UpdateStarted() returns true, the caller MUST eventually call
// UpdateFinished(). If it returns false, the caller MUST NOT call
// the other functions.
virtual bool UpdateStarted(std::vector<SBListChunkRanges>* lists) = 0;
virtual void InsertChunks(const std::string& list_name,
const SBChunkList& chunks) = 0;
virtual void DeleteChunks(
const std::vector<SBChunkDelete>& chunk_deletes) = 0;
virtual void UpdateFinished(bool update_succeeded) = 0;
// Store the results of a GetHash response. In the case of empty results, we
// cache the prefixes until the next update so that we don't have to issue
// further GetHash requests we know will be empty.
virtual void CacheHashResults(
const std::vector<SBPrefix>& prefixes,
const std::vector<SBFullHashResult>& full_hits) = 0;
// The name of the bloom-filter file for the given database file.
static FilePath BloomFilterForFilename(const FilePath& db_filename);
// Enumerate failures for histogramming purposes. DO NOT CHANGE THE
// ORDERING OF THESE VALUES.
enum FailureType {
FAILURE_DATABASE_CORRUPT,
FAILURE_DATABASE_CORRUPT_HANDLER,
FAILURE_DATABASE_UPDATE_BEGIN,
FAILURE_DATABASE_UPDATE_FINISH,
FAILURE_DATABASE_FILTER_MISSING,
FAILURE_DATABASE_FILTER_READ,
FAILURE_DATABASE_FILTER_WRITE,
FAILURE_DATABASE_FILTER_DELETE,
FAILURE_DATABASE_STORE_MISSING,
FAILURE_DATABASE_STORE_DELETE,
// Histogram space is determined by the max. If this is exceeded,
// simply start a new histogram.
FAILURE_MAX = 50
};
static void RecordFailure(FailureType failure_type);
};
class SafeBrowsingDatabaseNew : public SafeBrowsingDatabase {
public:
// Create a database on the given store. Takes ownership of
// |store|. This method is temporary for
// SafeBrowsingDatabase::Create(), do not use it otherwise.
explicit SafeBrowsingDatabaseNew(SafeBrowsingStore* store);
// Create a database with a default store.
SafeBrowsingDatabaseNew();
virtual ~SafeBrowsingDatabaseNew();
// Implement SafeBrowsingDatabase interface.
virtual void Init(const FilePath& filename);
virtual bool ResetDatabase();
virtual bool ContainsUrl(const GURL& url,
std::string* matching_list,
std::vector<SBPrefix>* prefix_hits,
std::vector<SBFullHashResult>* full_hits,
base::Time last_update);
virtual bool UpdateStarted(std::vector<SBListChunkRanges>* lists);
virtual void InsertChunks(const std::string& list_name,
const SBChunkList& chunks);
virtual void DeleteChunks(const std::vector<SBChunkDelete>& chunk_deletes);
virtual void UpdateFinished(bool update_succeeded);
virtual void CacheHashResults(const std::vector<SBPrefix>& prefixes,
const std::vector<SBFullHashResult>& full_hits);
private:
friend class SafeBrowsingDatabaseTest;
FRIEND_TEST(SafeBrowsingDatabaseTest, HashCaching);
// Deletes the files on disk.
bool Delete();
// Load the bloom filter off disk, or generates one if it doesn't exist.
void LoadBloomFilter();
// Writes the current bloom filter to disk.
void WriteBloomFilter();
// Helpers for handling database corruption.
// |OnHandleCorruptDatabase()| runs |ResetDatabase()| and sets
// |corruption_detected_|, |HandleCorruptDatabase()| posts
// |OnHandleCorruptDatabase()| to the current thread, to be run
// after the current task completes.
// TODO(shess): Wire things up to entirely abort the update
// transaction when this happens.
void HandleCorruptDatabase();
void OnHandleCorruptDatabase();
// Helpers for InsertChunks().
void InsertAdd(int chunk, SBPrefix host, const SBEntry* entry, int list_id);
void InsertAddChunks(int list_id, const SBChunkList& chunks);
void InsertSub(int chunk, SBPrefix host, const SBEntry* entry, int list_id);
void InsertSubChunks(int list_id, const SBChunkList& chunks);
// Used to verify that various calls are made from the thread the
// object was created on.
MessageLoop* creation_loop_;
// Lock for protecting access to variables that may be used on the
// IO thread. This includes |bloom_filter_|, |full_hashes_|,
// |pending_hashes_|, and |prefix_miss_cache_|.
Lock lookup_lock_;
// Underlying persistent store for chunk data.
FilePath filename_;
scoped_ptr<SafeBrowsingStore> store_;
// Bloom filter generated from the add-prefixes in |store_|.
FilePath bloom_filter_filename_;
scoped_refptr<BloomFilter> bloom_filter_;
// Cached full-hash items, ordered by prefix for efficient scanning.
// |full_hashes_| are items from |store_|, |pending_hashes_| are
// items from |CacheHashResults()|, which will be pushed to the
// store on the next update.
std::vector<SBAddFullHash> full_hashes_;
std::vector<SBAddFullHash> pending_hashes_;
// Cache of prefixes that returned empty results (no full hash
// match) to |CacheHashResults()|. Cached to prevent asking for
// them every time. Cleared on next update.
std::set<SBPrefix> prefix_miss_cache_;
// Used to schedule resetting the database because of corruption.
ScopedRunnableMethodFactory<SafeBrowsingDatabaseNew> reset_factory_;
// Set if corruption is detected during the course of an update.
// Causes the update functions to fail with no side effects, until
// the next call to |UpdateStarted()|.
bool corruption_detected_;
};
#endif // CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_DATABASE_H_
|