Remove unused field from extension_sorting.cc
[chromium-blink-merge.git] / chrome / browser / extensions / extension_blacklist_browsertest.cc
blob4051c9f1a6b78a8f9f416fbb77941e6fa5ad5398
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.
5 #include "base/run_loop.h"
6 #include "base/strings/stringprintf.h"
7 #include "chrome/browser/extensions/blacklist.h"
8 #include "chrome/browser/extensions/extension_browsertest.h"
9 #include "chrome/browser/extensions/extension_service.h"
10 #include "chrome/browser/extensions/extension_system.h"
11 #include "chrome/browser/ui/browser.h"
12 #include "chrome/common/chrome_notification_types.h"
13 #include "chrome/common/extensions/extension.h"
14 #include "chrome/common/extensions/extension_constants.h"
15 #include "content/public/browser/notification_details.h"
16 #include "content/public/browser/notification_observer.h"
17 #include "content/public/browser/notification_registrar.h"
18 #include "content/public/browser/notification_source.h"
20 namespace extensions {
22 namespace {
24 // Records notifications, but only for extensions with specific IDs.
25 class FilteringNotificationObserver : public content::NotificationObserver {
26 public:
27 FilteringNotificationObserver(
28 content::NotificationSource source,
29 const std::set<std::string>& extension_ids)
30 : extension_ids_(extension_ids) {
31 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, source);
32 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED, source);
33 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, source);
36 // Checks then clears notifications for our extensions.
37 testing::AssertionResult CheckNotifications(chrome::NotificationType type) {
38 return CheckNotifications(std::vector<chrome::NotificationType>(1, type));
41 // Checks then clears notifications for our extensions.
42 testing::AssertionResult CheckNotifications(chrome::NotificationType t1,
43 chrome::NotificationType t2) {
44 std::vector<chrome::NotificationType> types;
45 types.push_back(t1);
46 types.push_back(t2);
47 return CheckNotifications(types);
50 // Checks then clears notifications for our extensions.
51 testing::AssertionResult CheckNotifications(chrome::NotificationType t1,
52 chrome::NotificationType t2,
53 chrome::NotificationType t3) {
54 std::vector<chrome::NotificationType> types;
55 types.push_back(t1);
56 types.push_back(t2);
57 types.push_back(t3);
58 return CheckNotifications(types);
61 // Checks then clears notifications for our extensions.
62 testing::AssertionResult CheckNotifications(chrome::NotificationType t1,
63 chrome::NotificationType t2,
64 chrome::NotificationType t3,
65 chrome::NotificationType t4,
66 chrome::NotificationType t5,
67 chrome::NotificationType t6) {
68 std::vector<chrome::NotificationType> types;
69 types.push_back(t1);
70 types.push_back(t2);
71 types.push_back(t3);
72 types.push_back(t4);
73 types.push_back(t5);
74 types.push_back(t6);
75 return CheckNotifications(types);
78 private:
79 // content::NotificationObserver implementation.
80 virtual void Observe(int type,
81 const content::NotificationSource& source,
82 const content::NotificationDetails& details) OVERRIDE {
83 switch (type) {
84 case chrome::NOTIFICATION_EXTENSION_INSTALLED: {
85 const Extension* extension =
86 content::Details<const InstalledExtensionInfo>(details)->extension;
87 if (extension_ids_.count(extension->id()))
88 notifications_.push_back(static_cast<chrome::NotificationType>(type));
89 break;
92 case chrome::NOTIFICATION_EXTENSION_LOADED: {
93 const Extension* extension =
94 content::Details<const Extension>(details).ptr();
95 if (extension_ids_.count(extension->id()))
96 notifications_.push_back(static_cast<chrome::NotificationType>(type));
97 break;
100 case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
101 UnloadedExtensionInfo* reason =
102 content::Details<UnloadedExtensionInfo>(details).ptr();
103 if (extension_ids_.count(reason->extension->id())) {
104 notifications_.push_back(static_cast<chrome::NotificationType>(type));
105 // The only way that extensions are unloaded in these tests is
106 // by blacklisting.
107 EXPECT_EQ(extension_misc::UNLOAD_REASON_BLACKLIST,
108 reason->reason);
110 break;
113 default:
114 NOTREACHED();
115 break;
119 // Checks then clears notifications for our extensions.
120 testing::AssertionResult CheckNotifications(
121 const std::vector<chrome::NotificationType>& types) {
122 testing::AssertionResult result = (notifications_ == types) ?
123 testing::AssertionSuccess() :
124 testing::AssertionFailure() << "Expected " << Str(types) << ", " <<
125 "Got " << Str(notifications_);
126 notifications_.clear();
127 return result;
130 std::string Str(const std::vector<chrome::NotificationType>& types) {
131 std::string str = "[";
132 bool needs_comma = false;
133 for (std::vector<chrome::NotificationType>::const_iterator it =
134 types.begin(); it != types.end(); ++it) {
135 if (needs_comma)
136 str += ",";
137 needs_comma = true;
138 str += base::StringPrintf("%d", *it);
140 return str + "]";
143 const std::set<std::string> extension_ids_;
145 std::vector<chrome::NotificationType> notifications_;
147 content::NotificationRegistrar registrar_;
150 // Stores the paths to CRX files of extensions, and the extension's ID.
151 // Use arbitrary extensions; we're just testing blacklisting behavior.
152 class CrxInfo {
153 public:
154 CrxInfo(const std::string& path, const std::string& id)
155 : path_(path), id_(id) {}
157 const std::string& path() { return path_; }
158 const std::string& id() { return id_; }
160 private:
161 const std::string path_;
162 const std::string id_;
165 } // namespace
167 class ExtensionBlacklistBrowserTest : public ExtensionBrowserTest {
168 public:
169 ExtensionBlacklistBrowserTest()
170 : info_a_("install/install.crx", "ogdbpbegnmindpdjfafpmpicikegejdj"),
171 info_b_("autoupdate/v1.crx", "ogjcoiohnmldgjemafoockdghcjciccf"),
172 info_c_("hosted_app.crx", "kbmnembihfiondgfjekmnmcbddelicoi"),
173 // Just disable the safe browsing altogether.
174 // TODO(kalman): a different approach will be needed when the blacklist
175 // comes entirely from safe browsing.
176 scoped_blacklist_database_manager_(
177 scoped_refptr<SafeBrowsingDatabaseManager>(NULL)) {}
179 virtual ~ExtensionBlacklistBrowserTest() {}
181 protected:
182 // Returns whether |extension| is strictly safe: in one of ExtensionService's
183 // non-blacklisted extension sets, and not in its blacklisted extensions.
184 testing::AssertionResult IsSafe(const Extension* extension) {
185 std::string id = extension->id();
186 int include_mask = ExtensionService::INCLUDE_EVERYTHING &
187 ~ExtensionService::INCLUDE_BLACKLISTED;
188 if (!extension_service()->GetExtensionById(id, include_mask))
189 return testing::AssertionFailure() << id << " is safe";
190 return IsInValidState(extension);
193 // Returns whether |extension| is strictly blacklisted: in ExtensionService's
194 // blacklist, and not in any of its other extension sets.
195 testing::AssertionResult IsBlacklisted(const Extension* extension) {
196 std::string id = extension->id();
197 if (!extension_service()->blacklisted_extensions()->Contains(id))
198 return testing::AssertionFailure() << id << " is not blacklisted";
199 return IsInValidState(extension);
202 std::set<std::string> GetTestExtensionIDs() {
203 std::set<std::string> extension_ids;
204 extension_ids.insert(info_a_.id());
205 extension_ids.insert(info_b_.id());
206 extension_ids.insert(info_c_.id());
207 return extension_ids;
210 Blacklist* blacklist() {
211 return ExtensionSystem::Get(profile())->blacklist();
214 CrxInfo info_a_;
215 CrxInfo info_b_;
216 CrxInfo info_c_;
218 private:
219 // Returns whether |extension| is either installed or blacklisted, but
220 // neither both nor neither.
221 testing::AssertionResult IsInValidState(const Extension* extension) {
222 std::string id = extension->id();
223 bool is_blacklisted =
224 extension_service()->blacklisted_extensions()->Contains(id);
225 int safe_mask = ExtensionService::INCLUDE_EVERYTHING &
226 ~ExtensionService::INCLUDE_BLACKLISTED;
227 bool is_safe = extension_service()->GetExtensionById(id, safe_mask) != NULL;
228 if (is_blacklisted && is_safe) {
229 return testing::AssertionFailure() <<
230 id << " is both safe and in blacklisted_extensions";
232 if (!is_blacklisted && !is_safe) {
233 return testing::AssertionFailure() <<
234 id << " is neither safe nor in blacklisted_extensions";
236 return testing::AssertionSuccess();
239 Blacklist::ScopedDatabaseManagerForTest scoped_blacklist_database_manager_;
242 // Stage 1: blacklisting when there weren't any extensions installed when the
243 // browser started.
244 IN_PROC_BROWSER_TEST_F(ExtensionBlacklistBrowserTest, PRE_Blacklist) {
245 FilteringNotificationObserver notifications(
246 content::NotificationService::AllSources(), GetTestExtensionIDs());
248 scoped_refptr<const Extension> extension_a =
249 InstallExtension(test_data_dir_.AppendASCII(info_a_.path()), 1);
250 scoped_refptr<const Extension> extension_b =
251 InstallExtension(test_data_dir_.AppendASCII(info_b_.path()), 1);
252 scoped_refptr<const Extension> extension_c =
253 InstallExtension(test_data_dir_.AppendASCII(info_c_.path()), 1);
255 EXPECT_TRUE(notifications.CheckNotifications(
256 chrome::NOTIFICATION_EXTENSION_INSTALLED,
257 chrome::NOTIFICATION_EXTENSION_LOADED,
258 chrome::NOTIFICATION_EXTENSION_INSTALLED,
259 chrome::NOTIFICATION_EXTENSION_LOADED,
260 chrome::NOTIFICATION_EXTENSION_INSTALLED,
261 chrome::NOTIFICATION_EXTENSION_LOADED));
263 ASSERT_TRUE(extension_a.get());
264 ASSERT_TRUE(extension_b.get());
265 ASSERT_EQ(info_a_.id(), extension_a->id());
266 ASSERT_EQ(info_b_.id(), extension_b->id());
267 ASSERT_EQ(info_c_.id(), extension_c->id());
269 std::vector<std::string> empty_vector;
270 std::vector<std::string> vector_a(1, info_a_.id());
271 std::vector<std::string> vector_b(1, info_b_.id());
272 std::vector<std::string> vector_c(1, info_c_.id());
273 std::vector<std::string> vector_ab(1, info_a_.id());
274 vector_ab.push_back(info_b_.id());
275 std::vector<std::string> vector_bc(1, info_b_.id());
276 vector_bc.push_back(info_c_.id());
277 std::vector<std::string> vector_abc(1, info_a_.id());
278 vector_abc.push_back(info_b_.id());
279 vector_abc.push_back(info_c_.id());
281 EXPECT_TRUE(IsSafe(extension_a.get()));
282 EXPECT_TRUE(IsSafe(extension_b.get()));
283 EXPECT_TRUE(IsSafe(extension_c.get()));
285 // Blacklist a and b.
286 blacklist()->SetFromUpdater(vector_ab, "1");
287 base::RunLoop().RunUntilIdle();
289 EXPECT_TRUE(IsBlacklisted(extension_a.get()));
290 EXPECT_TRUE(IsBlacklisted(extension_b.get()));
291 EXPECT_TRUE(IsSafe(extension_c.get()));
292 EXPECT_TRUE(notifications.CheckNotifications(
293 chrome::NOTIFICATION_EXTENSION_UNLOADED,
294 chrome::NOTIFICATION_EXTENSION_UNLOADED));
296 // Un-blacklist a.
297 blacklist()->SetFromUpdater(vector_b, "2");
298 base::RunLoop().RunUntilIdle();
300 EXPECT_TRUE(IsSafe(extension_a.get()));
301 EXPECT_TRUE(IsBlacklisted(extension_b.get()));
302 EXPECT_TRUE(IsSafe(extension_c.get()));
303 EXPECT_TRUE(
304 notifications.CheckNotifications(chrome::NOTIFICATION_EXTENSION_LOADED));
306 // Blacklist a then switch with c.
307 blacklist()->SetFromUpdater(vector_ab, "3");
308 base::RunLoop().RunUntilIdle();
310 EXPECT_TRUE(IsBlacklisted(extension_a.get()));
311 EXPECT_TRUE(IsBlacklisted(extension_b.get()));
312 EXPECT_TRUE(IsSafe(extension_c.get()));
313 EXPECT_TRUE(notifications.CheckNotifications(
314 chrome::NOTIFICATION_EXTENSION_UNLOADED));
316 blacklist()->SetFromUpdater(vector_bc, "4");
317 base::RunLoop().RunUntilIdle();
319 EXPECT_TRUE(IsSafe(extension_a.get()));
320 EXPECT_TRUE(IsBlacklisted(extension_b.get()));
321 EXPECT_TRUE(IsBlacklisted(extension_c.get()));
322 EXPECT_TRUE(notifications.CheckNotifications(
323 chrome::NOTIFICATION_EXTENSION_LOADED,
324 chrome::NOTIFICATION_EXTENSION_UNLOADED));
326 // Add a to blacklist.
327 blacklist()->SetFromUpdater(vector_abc, "5");
328 base::RunLoop().RunUntilIdle();
330 EXPECT_TRUE(IsBlacklisted(extension_a.get()));
331 EXPECT_TRUE(IsBlacklisted(extension_b.get()));
332 EXPECT_TRUE(IsBlacklisted(extension_c.get()));
333 EXPECT_TRUE(notifications.CheckNotifications(
334 chrome::NOTIFICATION_EXTENSION_UNLOADED));
336 // Clear blacklist.
337 blacklist()->SetFromUpdater(empty_vector, "6");
338 base::RunLoop().RunUntilIdle();
340 EXPECT_TRUE(IsSafe(extension_a.get()));
341 EXPECT_TRUE(IsSafe(extension_b.get()));
342 EXPECT_TRUE(IsSafe(extension_c.get()));
343 EXPECT_TRUE(
344 notifications.CheckNotifications(chrome::NOTIFICATION_EXTENSION_LOADED,
345 chrome::NOTIFICATION_EXTENSION_LOADED,
346 chrome::NOTIFICATION_EXTENSION_LOADED));
348 // Add a and b back again for the next test.
349 blacklist()->SetFromUpdater(vector_ab, "7");
350 base::RunLoop().RunUntilIdle();
352 EXPECT_TRUE(IsBlacklisted(extension_a.get()));
353 EXPECT_TRUE(IsBlacklisted(extension_b.get()));
354 EXPECT_TRUE(IsSafe(extension_c.get()));
355 EXPECT_TRUE(notifications.CheckNotifications(
356 chrome::NOTIFICATION_EXTENSION_UNLOADED,
357 chrome::NOTIFICATION_EXTENSION_UNLOADED));
360 // Stage 2: blacklisting with extensions A and B having been installed,
361 // with A actually in the blacklist.
362 IN_PROC_BROWSER_TEST_F(ExtensionBlacklistBrowserTest, Blacklist) {
363 FilteringNotificationObserver notifications(
364 content::Source<Profile>(profile()), GetTestExtensionIDs());
366 scoped_refptr<const Extension> extension_a =
367 extension_service()->blacklisted_extensions()->GetByID(info_a_.id());
368 ASSERT_TRUE(extension_a.get());
370 scoped_refptr<const Extension> extension_b =
371 extension_service()->blacklisted_extensions()->GetByID(info_b_.id());
372 ASSERT_TRUE(extension_b.get());
374 scoped_refptr<const Extension> extension_c =
375 extension_service()->extensions()->GetByID(info_c_.id());
376 ASSERT_TRUE(extension_c.get());
378 EXPECT_TRUE(IsBlacklisted(extension_a.get()));
379 EXPECT_TRUE(IsBlacklisted(extension_b.get()));
380 EXPECT_TRUE(IsSafe(extension_c.get()));
382 // Make sure that we can still blacklist c and unblacklist b.
383 std::vector<std::string> vector_ac(1, extension_a->id());
384 vector_ac.push_back(extension_c->id());
385 blacklist()->SetFromUpdater(vector_ac, "8");
386 base::RunLoop().RunUntilIdle();
388 EXPECT_TRUE(IsBlacklisted(extension_a.get()));
389 EXPECT_TRUE(IsSafe(extension_b.get()));
390 EXPECT_TRUE(IsBlacklisted(extension_c.get()));
391 EXPECT_TRUE(notifications.CheckNotifications(
392 chrome::NOTIFICATION_EXTENSION_LOADED,
393 chrome::NOTIFICATION_EXTENSION_UNLOADED));
396 } // namespace extensions