1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef CHROME_BROWSER_EXTENSIONS_BLOCKLIST_H_
6 #define CHROME_BROWSER_EXTENSIONS_BLOCKLIST_H_
7 
8 #include <list>
9 #include <map>
10 #include <memory>
11 #include <set>
12 #include <string>
13 #include <vector>
14 
15 #include "base/callback.h"
16 #include "base/callback_list.h"
17 #include "base/macros.h"
18 #include "base/memory/weak_ptr.h"
19 #include "base/observer_list.h"
20 #include "components/keyed_service/core/keyed_service.h"
21 #include "components/safe_browsing/core/db/database_manager.h"
22 #include "extensions/browser/blocklist_state.h"
23 
24 namespace content {
25 class BrowserContext;
26 }
27 
28 namespace extensions {
29 
30 class BlocklistStateFetcher;
31 class ExtensionPrefs;
32 
33 // The blocklist of extensions backed by safe browsing.
34 class Blocklist : public KeyedService, public base::SupportsWeakPtr<Blocklist> {
35  public:
36   class Observer {
37    public:
38     // Observes |blocklist| on construction and unobserves on destruction.
39     explicit Observer(Blocklist* blocklist);
40 
41     virtual void OnBlocklistUpdated() = 0;
42 
43    protected:
44     virtual ~Observer();
45 
46    private:
47     Blocklist* blocklist_;
48   };
49 
50   class ScopedDatabaseManagerForTest {
51    public:
52     explicit ScopedDatabaseManagerForTest(
53         scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager>
54             database_manager);
55 
56     ~ScopedDatabaseManagerForTest();
57 
58    private:
59     scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> original_;
60 
61     DISALLOW_COPY_AND_ASSIGN(ScopedDatabaseManagerForTest);
62   };
63 
64   using BlocklistStateMap = std::map<std::string, BlocklistState>;
65 
66   using GetBlocklistedIDsCallback =
67       base::OnceCallback<void(const BlocklistStateMap&)>;
68 
69   using GetMalwareIDsCallback =
70       base::OnceCallback<void(const std::set<std::string>&)>;
71 
72   using IsBlocklistedCallback = base::OnceCallback<void(BlocklistState)>;
73 
74   explicit Blocklist(ExtensionPrefs* prefs);
75 
76   ~Blocklist() override;
77 
78   static Blocklist* Get(content::BrowserContext* context);
79 
80   // From the set of extension IDs passed in via |ids|, asynchronously checks
81   // which are blocklisted and includes them in the resulting map passed
82   // via |callback|, which will be sent on the caller's message loop. The values
83   // of the map are the blocklist state for each extension. Extensions with
84   // a BlocklistState of NOT_BLOCKLISTED are not included in the result.
85   //
86   // For a synchronous version which ONLY CHECKS CURRENTLY INSTALLED EXTENSIONS
87   // see ExtensionPrefs::IsExtensionBlocklisted.
88   void GetBlocklistedIDs(const std::set<std::string>& ids,
89                          GetBlocklistedIDsCallback callback);
90 
91   // From the subset of extension IDs passed in via |ids|, select the ones
92   // marked in the blocklist as BLOCKLISTED_MALWARE and asynchronously pass
93   // to |callback|. Basically, will call GetBlocklistedIDs and filter its
94   // results.
95   void GetMalwareIDs(const std::set<std::string>& ids,
96                      GetMalwareIDsCallback callback);
97 
98   // More convenient form of GetBlocklistedIDs for checking a single extension.
99   void IsBlocklisted(const std::string& extension_id,
100                      IsBlocklistedCallback callback);
101 
102   // Used to mock BlocklistStateFetcher in unit tests. Blocklist owns the
103   // |fetcher|.
104   void SetBlocklistStateFetcherForTest(BlocklistStateFetcher* fetcher);
105 
106   // Reset the owned BlocklistStateFetcher to null and return the current
107   // BlocklistStateFetcher.
108   BlocklistStateFetcher* ResetBlocklistStateFetcherForTest();
109 
110   // Reset the listening for an updated database.
111   void ResetDatabaseUpdatedListenerForTest();
112 
113   // Adds/removes an observer to the blocklist.
114   void AddObserver(Observer* observer);
115   void RemoveObserver(Observer* observer);
116 
117  private:
118   // Use via ScopedDatabaseManagerForTest.
119   static void SetDatabaseManager(
120       scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager>
121           database_manager);
122   static scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager>
123   GetDatabaseManager();
124 
125   void ObserveNewDatabase();
126 
127   void NotifyObservers();
128 
129   void GetBlocklistStateForIDs(GetBlocklistedIDsCallback callback,
130                                const std::set<std::string>& blocklisted_ids);
131 
132   void RequestExtensionsBlocklistState(const std::set<std::string>& ids,
133                                        base::OnceClosure callback);
134 
135   void OnBlocklistStateReceived(const std::string& id, BlocklistState state);
136 
137   void ReturnBlocklistStateMap(GetBlocklistedIDsCallback callback,
138                                const std::set<std::string>& blocklisted_ids);
139 
140   base::ObserverList<Observer>::Unchecked observers_;
141 
142   std::unique_ptr<base::RepeatingClosureList::Subscription>
143       database_updated_subscription_;
144   std::unique_ptr<base::RepeatingClosureList::Subscription>
145       database_changed_subscription_;
146 
147   // The cached BlocklistState's, received from BlocklistStateFetcher.
148   BlocklistStateMap blocklist_state_cache_;
149 
150   std::unique_ptr<BlocklistStateFetcher> state_fetcher_;
151 
152   // The list of ongoing requests for blocklist states that couldn't be
153   // served directly from the cache. A new request is created in
154   // GetBlocklistedIDs and deleted when the callback is called from
155   // OnBlocklistStateReceived.
156   //
157   // This is a list of requests. Each item in the list is a request. A request
158   // is a pair of [vector of string ids to check, response closure].
159   std::list<std::pair<std::vector<std::string>, base::OnceClosure>>
160       state_requests_;
161 
162   DISALLOW_COPY_AND_ASSIGN(Blocklist);
163 };
164 
165 }  // namespace extensions
166 
167 #endif  // CHROME_BROWSER_EXTENSIONS_BLOCKLIST_H_
168