1// Copyright 2012 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#include "base/bind.h"
6#include "base/message_loop/message_loop.h"
7#include "base/run_loop.h"
8#include "base/stl_util.h"
9#include "chrome/browser/extensions/blacklist.h"
10#include "chrome/browser/extensions/blacklist_state_fetcher.h"
11#include "chrome/browser/extensions/fake_safe_browsing_database_manager.h"
12#include "chrome/browser/extensions/test_blacklist.h"
13#include "chrome/browser/extensions/test_blacklist_state_fetcher.h"
14#include "chrome/browser/extensions/test_extension_prefs.h"
15#include "content/public/test/test_browser_thread_bundle.h"
16#include "extensions/browser/extension_prefs.h"
17#include "testing/gtest/include/gtest/gtest.h"
18
19namespace extensions {
20namespace {
21
22std::set<std::string> Set(const std::string& a) {
23  std::set<std::string> set;
24  set.insert(a);
25  return set;
26}
27std::set<std::string> Set(const std::string& a, const std::string& b) {
28  std::set<std::string> set = Set(a);
29  set.insert(b);
30  return set;
31}
32std::set<std::string> Set(const std::string& a,
33                          const std::string& b,
34                          const std::string& c) {
35  std::set<std::string> set = Set(a, b);
36  set.insert(c);
37  return set;
38}
39std::set<std::string> Set(const std::string& a,
40                          const std::string& b,
41                          const std::string& c,
42                          const std::string& d) {
43  std::set<std::string> set = Set(a, b, c);
44  set.insert(d);
45  return set;
46}
47
48class BlacklistTest : public testing::Test {
49 public:
50  BlacklistTest()
51      : test_prefs_(base::MessageLoopProxy::current()) {}
52
53 protected:
54  ExtensionPrefs* prefs() {
55    return test_prefs_.prefs();
56  }
57
58  std::string AddExtension(const std::string& id) {
59    return test_prefs_.AddExtension(id)->id();
60  }
61
62 private:
63  content::TestBrowserThreadBundle browser_thread_bundle_;
64
65  TestExtensionPrefs test_prefs_;
66};
67
68template<typename T>
69void Assign(T *to, const T& from) {
70  *to = from;
71}
72
73}  // namespace
74
75TEST_F(BlacklistTest, OnlyIncludesRequestedIDs) {
76  std::string a = AddExtension("a");
77  std::string b = AddExtension("b");
78  std::string c = AddExtension("c");
79
80  Blacklist blacklist(prefs());
81  TestBlacklist tester(&blacklist);
82  tester.SetBlacklistState(a, BLACKLISTED_MALWARE, false);
83  tester.SetBlacklistState(b, BLACKLISTED_MALWARE, false);
84
85  EXPECT_EQ(BLACKLISTED_MALWARE, tester.GetBlacklistState(a));
86  EXPECT_EQ(BLACKLISTED_MALWARE, tester.GetBlacklistState(b));
87  EXPECT_EQ(NOT_BLACKLISTED, tester.GetBlacklistState(c));
88
89  std::set<std::string> blacklisted_ids;
90  blacklist.GetMalwareIDs(
91      Set(a, c), base::Bind(&Assign<std::set<std::string> >, &blacklisted_ids));
92  base::RunLoop().RunUntilIdle();
93
94  EXPECT_EQ(Set(a), blacklisted_ids);
95}
96
97TEST_F(BlacklistTest, SafeBrowsing) {
98  std::string a = AddExtension("a");
99
100  Blacklist blacklist(prefs());
101  TestBlacklist tester(&blacklist);
102  tester.DisableSafeBrowsing();
103
104  EXPECT_EQ(NOT_BLACKLISTED, tester.GetBlacklistState(a));
105
106  tester.SetBlacklistState(a, BLACKLISTED_MALWARE, false);
107  // The manager is still disabled at this point, so it won't be blacklisted.
108  EXPECT_EQ(NOT_BLACKLISTED, tester.GetBlacklistState(a));
109
110  tester.EnableSafeBrowsing();
111  tester.NotifyUpdate();
112  base::RunLoop().RunUntilIdle();
113  // Now it should be.
114  EXPECT_EQ(BLACKLISTED_MALWARE, tester.GetBlacklistState(a));
115
116  tester.Clear(true);
117  // Safe browsing blacklist empty, now enabled.
118  EXPECT_EQ(NOT_BLACKLISTED, tester.GetBlacklistState(a));
119}
120
121// Tests that Blacklist clears the old prefs blacklist on startup.
122TEST_F(BlacklistTest, ClearsPreferencesBlacklist) {
123  std::string a = AddExtension("a");
124  std::string b = AddExtension("b");
125
126  // Blacklist an installed extension.
127  prefs()->SetExtensionBlacklisted(a, true);
128
129  // Blacklist some non-installed extensions. This is what the old preferences
130  // blacklist looked like.
131  std::string c = "cccccccccccccccccccccccccccccccc";
132  std::string d = "dddddddddddddddddddddddddddddddd";
133  prefs()->SetExtensionBlacklisted(c, true);
134  prefs()->SetExtensionBlacklisted(d, true);
135
136  EXPECT_EQ(Set(a, c, d), prefs()->GetBlacklistedExtensions());
137
138  Blacklist blacklist(prefs());
139  TestBlacklist tester(&blacklist);
140
141  // Blacklist has been cleared. Only the installed extension "a" left.
142  EXPECT_EQ(Set(a), prefs()->GetBlacklistedExtensions());
143  EXPECT_TRUE(prefs()->GetInstalledExtensionInfo(a).get());
144  EXPECT_TRUE(prefs()->GetInstalledExtensionInfo(b).get());
145
146  // "a" won't actually be *blacklisted* since it doesn't appear in
147  // safebrowsing. Blacklist no longer reads from prefs. This is purely a
148  // concern of somebody else (currently, ExtensionService).
149  std::set<std::string> blacklisted_ids;
150  blacklist.GetMalwareIDs(Set(a, b, c, d),
151                          base::Bind(&Assign<std::set<std::string> >,
152                                     &blacklisted_ids));
153  base::RunLoop().RunUntilIdle();
154  EXPECT_EQ(std::set<std::string>(), blacklisted_ids);
155
156  // Prefs are still unaffected for installed extensions, though.
157  EXPECT_TRUE(prefs()->IsExtensionBlacklisted(a));
158  EXPECT_FALSE(prefs()->IsExtensionBlacklisted(b));
159  EXPECT_FALSE(prefs()->IsExtensionBlacklisted(c));
160  EXPECT_FALSE(prefs()->IsExtensionBlacklisted(d));
161}
162
163// Test getting different blacklist states from Blacklist.
164TEST_F(BlacklistTest, GetBlacklistStates) {
165  Blacklist blacklist(prefs());
166  TestBlacklist tester(&blacklist);
167
168  std::string a = AddExtension("a");
169  std::string b = AddExtension("b");
170  std::string c = AddExtension("c");
171  std::string d = AddExtension("d");
172  std::string e = AddExtension("e");
173
174  tester.SetBlacklistState(a, BLACKLISTED_MALWARE, false);
175  tester.SetBlacklistState(b, BLACKLISTED_SECURITY_VULNERABILITY, false);
176  tester.SetBlacklistState(c, BLACKLISTED_CWS_POLICY_VIOLATION, false);
177  tester.SetBlacklistState(d, BLACKLISTED_POTENTIALLY_UNWANTED, false);
178
179  Blacklist::BlacklistStateMap states_abc;
180  Blacklist::BlacklistStateMap states_bcd;
181  blacklist.GetBlacklistedIDs(Set(a, b, c, e),
182                              base::Bind(&Assign<Blacklist::BlacklistStateMap>,
183                                         &states_abc));
184  blacklist.GetBlacklistedIDs(Set(b, c, d, e),
185                              base::Bind(&Assign<Blacklist::BlacklistStateMap>,
186                                         &states_bcd));
187  base::RunLoop().RunUntilIdle();
188
189  EXPECT_EQ(BLACKLISTED_MALWARE, states_abc[a]);
190  EXPECT_EQ(BLACKLISTED_SECURITY_VULNERABILITY, states_abc[b]);
191  EXPECT_EQ(BLACKLISTED_CWS_POLICY_VIOLATION, states_abc[c]);
192  EXPECT_EQ(BLACKLISTED_SECURITY_VULNERABILITY, states_bcd[b]);
193  EXPECT_EQ(BLACKLISTED_CWS_POLICY_VIOLATION, states_bcd[c]);
194  EXPECT_EQ(BLACKLISTED_POTENTIALLY_UNWANTED, states_bcd[d]);
195  EXPECT_EQ(0U, states_abc.count(e));
196  EXPECT_EQ(0U, states_bcd.count(e));
197
198  int old_request_count = tester.fetcher()->request_count();
199  Blacklist::BlacklistStateMap states_ad;
200  blacklist.GetBlacklistedIDs(Set(a, d, e),
201                              base::Bind(&Assign<Blacklist::BlacklistStateMap>,
202                                         &states_ad));
203  base::RunLoop().RunUntilIdle();
204  EXPECT_EQ(BLACKLISTED_MALWARE, states_ad[a]);
205  EXPECT_EQ(BLACKLISTED_POTENTIALLY_UNWANTED, states_ad[d]);
206  EXPECT_EQ(0U, states_ad.count(e));
207  EXPECT_EQ(old_request_count, tester.fetcher()->request_count());
208}
209
210// Test both Blacklist and BlacklistStateFetcher by requesting the blacklist
211// states, sending fake requests and parsing the responses.
212TEST_F(BlacklistTest, FetchBlacklistStates) {
213  Blacklist blacklist(prefs());
214  scoped_refptr<FakeSafeBrowsingDatabaseManager> blacklist_db(
215      new FakeSafeBrowsingDatabaseManager(true));
216  Blacklist::ScopedDatabaseManagerForTest scoped_blacklist_db(blacklist_db);
217
218  std::string a = AddExtension("a");
219  std::string b = AddExtension("b");
220  std::string c = AddExtension("c");
221
222  blacklist_db->Enable();
223  blacklist_db->SetUnsafe(a, b);
224
225  // Prepare real fetcher.
226  BlacklistStateFetcher* fetcher = new BlacklistStateFetcher();
227  TestBlacklistStateFetcher fetcher_tester(fetcher);
228  blacklist.SetBlacklistStateFetcherForTest(fetcher);
229
230  fetcher_tester.SetBlacklistVerdict(
231      a, ClientCRXListInfoResponse_Verdict_CWS_POLICY_VIOLATION);
232  fetcher_tester.SetBlacklistVerdict(
233      b, ClientCRXListInfoResponse_Verdict_POTENTIALLY_UNWANTED);
234
235  Blacklist::BlacklistStateMap states;
236  blacklist.GetBlacklistedIDs(
237      Set(a, b, c), base::Bind(&Assign<Blacklist::BlacklistStateMap>, &states));
238  base::RunLoop().RunUntilIdle();
239
240   // Two fetchers should be created.
241  EXPECT_TRUE(fetcher_tester.HandleFetcher(0));
242  EXPECT_TRUE(fetcher_tester.HandleFetcher(1));
243
244  EXPECT_EQ(BLACKLISTED_CWS_POLICY_VIOLATION, states[a]);
245  EXPECT_EQ(BLACKLISTED_POTENTIALLY_UNWANTED, states[b]);
246  EXPECT_EQ(0U, states.count(c));
247
248  Blacklist::BlacklistStateMap cached_states;
249
250  blacklist.GetBlacklistedIDs(
251      Set(a, b, c), base::Bind(&Assign<Blacklist::BlacklistStateMap>,
252                               &cached_states));
253  base::RunLoop().RunUntilIdle();
254
255  // No new fetchers.
256  EXPECT_FALSE(fetcher_tester.HandleFetcher(2));
257  EXPECT_EQ(BLACKLISTED_CWS_POLICY_VIOLATION, cached_states[a]);
258  EXPECT_EQ(BLACKLISTED_POTENTIALLY_UNWANTED, cached_states[b]);
259  EXPECT_EQ(0U, cached_states.count(c));
260}
261
262}  // namespace extensions
263