| OLD | NEW |
| (Empty) |
| 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/run_loop.h" | |
| 6 #include "chrome/browser/extensions/blacklist.h" | |
| 7 #include "chrome/browser/extensions/extension_browsertest.h" | |
| 8 #include "chrome/browser/extensions/extension_notification_observer.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/extensions/extension.h" | |
| 13 #include "chrome/common/extensions/extension_constants.h" | |
| 14 | |
| 15 namespace extensions { | |
| 16 | |
| 17 namespace { | |
| 18 | |
| 19 // Stores the paths to CRX files of extensions, and the extension's ID. | |
| 20 // Use arbitrary extensions; we're just testing blacklisting behavior. | |
| 21 class CrxInfo { | |
| 22 public: | |
| 23 CrxInfo(const std::string& path, const std::string& id) | |
| 24 : path_(path), id_(id) {} | |
| 25 | |
| 26 const std::string& path() { return path_; } | |
| 27 const std::string& id() { return id_; } | |
| 28 | |
| 29 private: | |
| 30 const std::string path_; | |
| 31 const std::string id_; | |
| 32 }; | |
| 33 | |
| 34 } // namespace | |
| 35 | |
| 36 class ExtensionBlacklistBrowserTest : public ExtensionBrowserTest { | |
| 37 public: | |
| 38 ExtensionBlacklistBrowserTest() | |
| 39 : info_a_("install/install.crx", "ogdbpbegnmindpdjfafpmpicikegejdj"), | |
| 40 info_b_("autoupdate/v1.crx", "ogjcoiohnmldgjemafoockdghcjciccf"), | |
| 41 info_c_("hosted_app.crx", "kbmnembihfiondgfjekmnmcbddelicoi"), | |
| 42 // Just disable the safe browsing altogether. | |
| 43 // TODO(kalman): a different approach will be needed when the blacklist | |
| 44 // comes entirely from safe browsing. | |
| 45 scoped_blacklist_database_manager_( | |
| 46 scoped_refptr<SafeBrowsingDatabaseManager>(NULL)) {} | |
| 47 | |
| 48 virtual ~ExtensionBlacklistBrowserTest() {} | |
| 49 | |
| 50 protected: | |
| 51 // Returns whether |extension| is strictly safe: in one of ExtensionService's | |
| 52 // non-blacklisted extension sets, and not in its blacklisted extensions. | |
| 53 testing::AssertionResult IsSafe(const Extension* extension) { | |
| 54 std::string id = extension->id(); | |
| 55 int include_mask = ExtensionService::INCLUDE_EVERYTHING & | |
| 56 ~ExtensionService::INCLUDE_BLACKLISTED; | |
| 57 if (!extension_service()->GetExtensionById(id, include_mask)) | |
| 58 return testing::AssertionFailure() << id << " is safe"; | |
| 59 return IsInValidState(extension); | |
| 60 } | |
| 61 | |
| 62 // Returns whether |extension| is strictly blacklisted: in ExtensionService's | |
| 63 // blacklist, and not in any of its other extension sets. | |
| 64 testing::AssertionResult IsBlacklisted(const Extension* extension) { | |
| 65 std::string id = extension->id(); | |
| 66 if (!extension_service()->blacklisted_extensions()->Contains(id)) | |
| 67 return testing::AssertionFailure() << id << " is not blacklisted"; | |
| 68 return IsInValidState(extension); | |
| 69 } | |
| 70 | |
| 71 std::set<std::string> GetTestExtensionIDs() { | |
| 72 std::set<std::string> extension_ids; | |
| 73 extension_ids.insert(info_a_.id()); | |
| 74 extension_ids.insert(info_b_.id()); | |
| 75 extension_ids.insert(info_c_.id()); | |
| 76 return extension_ids; | |
| 77 } | |
| 78 | |
| 79 Blacklist* blacklist() { | |
| 80 return ExtensionSystem::Get(profile())->blacklist(); | |
| 81 } | |
| 82 | |
| 83 CrxInfo info_a_; | |
| 84 CrxInfo info_b_; | |
| 85 CrxInfo info_c_; | |
| 86 | |
| 87 private: | |
| 88 // Returns whether |extension| is either installed or blacklisted, but | |
| 89 // neither both nor neither. | |
| 90 testing::AssertionResult IsInValidState(const Extension* extension) { | |
| 91 std::string id = extension->id(); | |
| 92 bool is_blacklisted = | |
| 93 extension_service()->blacklisted_extensions()->Contains(id); | |
| 94 int safe_mask = ExtensionService::INCLUDE_EVERYTHING & | |
| 95 ~ExtensionService::INCLUDE_BLACKLISTED; | |
| 96 bool is_safe = extension_service()->GetExtensionById(id, safe_mask) != NULL; | |
| 97 if (is_blacklisted && is_safe) { | |
| 98 return testing::AssertionFailure() << | |
| 99 id << " is both safe and in blacklisted_extensions"; | |
| 100 } | |
| 101 if (!is_blacklisted && !is_safe) { | |
| 102 return testing::AssertionFailure() << | |
| 103 id << " is neither safe nor in blacklisted_extensions"; | |
| 104 } | |
| 105 return testing::AssertionSuccess(); | |
| 106 } | |
| 107 | |
| 108 Blacklist::ScopedDatabaseManagerForTest scoped_blacklist_database_manager_; | |
| 109 }; | |
| 110 | |
| 111 // Stage 1: blacklisting when there weren't any extensions installed when the | |
| 112 // browser started. | |
| 113 IN_PROC_BROWSER_TEST_F(ExtensionBlacklistBrowserTest, PRE_Blacklist) { | |
| 114 ExtensionNotificationObserver notifications( | |
| 115 content::NotificationService::AllSources(), GetTestExtensionIDs()); | |
| 116 | |
| 117 scoped_refptr<const Extension> extension_a = | |
| 118 InstallExtension(test_data_dir_.AppendASCII(info_a_.path()), 1); | |
| 119 scoped_refptr<const Extension> extension_b = | |
| 120 InstallExtension(test_data_dir_.AppendASCII(info_b_.path()), 1); | |
| 121 scoped_refptr<const Extension> extension_c = | |
| 122 InstallExtension(test_data_dir_.AppendASCII(info_c_.path()), 1); | |
| 123 | |
| 124 EXPECT_TRUE(notifications.CheckNotifications( | |
| 125 chrome::NOTIFICATION_EXTENSION_INSTALLED, | |
| 126 chrome::NOTIFICATION_EXTENSION_LOADED, | |
| 127 chrome::NOTIFICATION_EXTENSION_INSTALLED, | |
| 128 chrome::NOTIFICATION_EXTENSION_LOADED, | |
| 129 chrome::NOTIFICATION_EXTENSION_INSTALLED, | |
| 130 chrome::NOTIFICATION_EXTENSION_LOADED)); | |
| 131 | |
| 132 ASSERT_TRUE(extension_a.get()); | |
| 133 ASSERT_TRUE(extension_b.get()); | |
| 134 ASSERT_EQ(info_a_.id(), extension_a->id()); | |
| 135 ASSERT_EQ(info_b_.id(), extension_b->id()); | |
| 136 ASSERT_EQ(info_c_.id(), extension_c->id()); | |
| 137 | |
| 138 std::vector<std::string> empty_vector; | |
| 139 std::vector<std::string> vector_a(1, info_a_.id()); | |
| 140 std::vector<std::string> vector_b(1, info_b_.id()); | |
| 141 std::vector<std::string> vector_c(1, info_c_.id()); | |
| 142 std::vector<std::string> vector_ab(1, info_a_.id()); | |
| 143 vector_ab.push_back(info_b_.id()); | |
| 144 std::vector<std::string> vector_bc(1, info_b_.id()); | |
| 145 vector_bc.push_back(info_c_.id()); | |
| 146 std::vector<std::string> vector_abc(1, info_a_.id()); | |
| 147 vector_abc.push_back(info_b_.id()); | |
| 148 vector_abc.push_back(info_c_.id()); | |
| 149 | |
| 150 EXPECT_TRUE(IsSafe(extension_a.get())); | |
| 151 EXPECT_TRUE(IsSafe(extension_b.get())); | |
| 152 EXPECT_TRUE(IsSafe(extension_c.get())); | |
| 153 | |
| 154 // Blacklist a and b. | |
| 155 blacklist()->SetFromUpdater(vector_ab, "1"); | |
| 156 base::RunLoop().RunUntilIdle(); | |
| 157 | |
| 158 EXPECT_TRUE(IsBlacklisted(extension_a.get())); | |
| 159 EXPECT_TRUE(IsBlacklisted(extension_b.get())); | |
| 160 EXPECT_TRUE(IsSafe(extension_c.get())); | |
| 161 EXPECT_TRUE(notifications.CheckNotifications( | |
| 162 chrome::NOTIFICATION_EXTENSION_UNLOADED, | |
| 163 chrome::NOTIFICATION_EXTENSION_UNLOADED)); | |
| 164 | |
| 165 // Un-blacklist a. | |
| 166 blacklist()->SetFromUpdater(vector_b, "2"); | |
| 167 base::RunLoop().RunUntilIdle(); | |
| 168 | |
| 169 EXPECT_TRUE(IsSafe(extension_a.get())); | |
| 170 EXPECT_TRUE(IsBlacklisted(extension_b.get())); | |
| 171 EXPECT_TRUE(IsSafe(extension_c.get())); | |
| 172 EXPECT_TRUE( | |
| 173 notifications.CheckNotifications(chrome::NOTIFICATION_EXTENSION_LOADED)); | |
| 174 | |
| 175 // Blacklist a then switch with c. | |
| 176 blacklist()->SetFromUpdater(vector_ab, "3"); | |
| 177 base::RunLoop().RunUntilIdle(); | |
| 178 | |
| 179 EXPECT_TRUE(IsBlacklisted(extension_a.get())); | |
| 180 EXPECT_TRUE(IsBlacklisted(extension_b.get())); | |
| 181 EXPECT_TRUE(IsSafe(extension_c.get())); | |
| 182 EXPECT_TRUE(notifications.CheckNotifications( | |
| 183 chrome::NOTIFICATION_EXTENSION_UNLOADED)); | |
| 184 | |
| 185 blacklist()->SetFromUpdater(vector_bc, "4"); | |
| 186 base::RunLoop().RunUntilIdle(); | |
| 187 | |
| 188 EXPECT_TRUE(IsSafe(extension_a.get())); | |
| 189 EXPECT_TRUE(IsBlacklisted(extension_b.get())); | |
| 190 EXPECT_TRUE(IsBlacklisted(extension_c.get())); | |
| 191 EXPECT_TRUE(notifications.CheckNotifications( | |
| 192 chrome::NOTIFICATION_EXTENSION_LOADED, | |
| 193 chrome::NOTIFICATION_EXTENSION_UNLOADED)); | |
| 194 | |
| 195 // Add a to blacklist. | |
| 196 blacklist()->SetFromUpdater(vector_abc, "5"); | |
| 197 base::RunLoop().RunUntilIdle(); | |
| 198 | |
| 199 EXPECT_TRUE(IsBlacklisted(extension_a.get())); | |
| 200 EXPECT_TRUE(IsBlacklisted(extension_b.get())); | |
| 201 EXPECT_TRUE(IsBlacklisted(extension_c.get())); | |
| 202 EXPECT_TRUE(notifications.CheckNotifications( | |
| 203 chrome::NOTIFICATION_EXTENSION_UNLOADED)); | |
| 204 | |
| 205 // Clear blacklist. | |
| 206 blacklist()->SetFromUpdater(empty_vector, "6"); | |
| 207 base::RunLoop().RunUntilIdle(); | |
| 208 | |
| 209 EXPECT_TRUE(IsSafe(extension_a.get())); | |
| 210 EXPECT_TRUE(IsSafe(extension_b.get())); | |
| 211 EXPECT_TRUE(IsSafe(extension_c.get())); | |
| 212 EXPECT_TRUE( | |
| 213 notifications.CheckNotifications(chrome::NOTIFICATION_EXTENSION_LOADED, | |
| 214 chrome::NOTIFICATION_EXTENSION_LOADED, | |
| 215 chrome::NOTIFICATION_EXTENSION_LOADED)); | |
| 216 | |
| 217 // Add a and b back again for the next test. | |
| 218 blacklist()->SetFromUpdater(vector_ab, "7"); | |
| 219 base::RunLoop().RunUntilIdle(); | |
| 220 | |
| 221 EXPECT_TRUE(IsBlacklisted(extension_a.get())); | |
| 222 EXPECT_TRUE(IsBlacklisted(extension_b.get())); | |
| 223 EXPECT_TRUE(IsSafe(extension_c.get())); | |
| 224 EXPECT_TRUE(notifications.CheckNotifications( | |
| 225 chrome::NOTIFICATION_EXTENSION_UNLOADED, | |
| 226 chrome::NOTIFICATION_EXTENSION_UNLOADED)); | |
| 227 } | |
| 228 | |
| 229 // Stage 2: blacklisting with extensions A and B having been installed, | |
| 230 // with A actually in the blacklist. | |
| 231 IN_PROC_BROWSER_TEST_F(ExtensionBlacklistBrowserTest, Blacklist) { | |
| 232 ExtensionNotificationObserver notifications( | |
| 233 content::Source<Profile>(profile()), GetTestExtensionIDs()); | |
| 234 | |
| 235 scoped_refptr<const Extension> extension_a = | |
| 236 extension_service()->blacklisted_extensions()->GetByID(info_a_.id()); | |
| 237 ASSERT_TRUE(extension_a.get()); | |
| 238 | |
| 239 scoped_refptr<const Extension> extension_b = | |
| 240 extension_service()->blacklisted_extensions()->GetByID(info_b_.id()); | |
| 241 ASSERT_TRUE(extension_b.get()); | |
| 242 | |
| 243 scoped_refptr<const Extension> extension_c = | |
| 244 extension_service()->extensions()->GetByID(info_c_.id()); | |
| 245 ASSERT_TRUE(extension_c.get()); | |
| 246 | |
| 247 EXPECT_TRUE(IsBlacklisted(extension_a.get())); | |
| 248 EXPECT_TRUE(IsBlacklisted(extension_b.get())); | |
| 249 EXPECT_TRUE(IsSafe(extension_c.get())); | |
| 250 | |
| 251 // Make sure that we can still blacklist c and unblacklist b. | |
| 252 std::vector<std::string> vector_ac(1, extension_a->id()); | |
| 253 vector_ac.push_back(extension_c->id()); | |
| 254 blacklist()->SetFromUpdater(vector_ac, "8"); | |
| 255 base::RunLoop().RunUntilIdle(); | |
| 256 | |
| 257 EXPECT_TRUE(IsBlacklisted(extension_a.get())); | |
| 258 EXPECT_TRUE(IsSafe(extension_b.get())); | |
| 259 EXPECT_TRUE(IsBlacklisted(extension_c.get())); | |
| 260 EXPECT_TRUE(notifications.CheckNotifications( | |
| 261 chrome::NOTIFICATION_EXTENSION_LOADED, | |
| 262 chrome::NOTIFICATION_EXTENSION_UNLOADED)); | |
| 263 } | |
| 264 | |
| 265 } // namespace extensions | |
| OLD | NEW |