OLD | NEW |
| (Empty) |
1 // Copyright 2014 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 "chrome/browser/extensions/extension_install_checker.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/location.h" | |
9 #include "base/memory/ptr_util.h" | |
10 #include "base/run_loop.h" | |
11 #include "base/single_thread_task_runner.h" | |
12 #include "base/strings/utf_string_conversions.h" | |
13 #include "base/threading/thread_task_runner_handle.h" | |
14 #include "extensions/browser/preload_check_test_util.h" | |
15 #include "testing/gtest/include/gtest/gtest.h" | |
16 | |
17 namespace extensions { | |
18 | |
19 namespace { | |
20 | |
21 const PreloadCheck::Error kBlacklistError = PreloadCheck::BLACKLISTED_ID; | |
22 const char kDummyRequirementsError[] = "Requirements error"; | |
23 const char kDummyPolicyError[] = "Cannot install extension"; | |
24 | |
25 } // namespace | |
26 | |
27 // Stubs most of the checks since we are interested in validating the logic in | |
28 // the install checker. This class implements a synchronous version of all | |
29 // checks. | |
30 class ExtensionInstallCheckerForTest : public ExtensionInstallChecker { | |
31 public: | |
32 ExtensionInstallCheckerForTest(int enabled_checks, bool fail_fast) | |
33 : ExtensionInstallChecker(nullptr, nullptr, enabled_checks, fail_fast) {} | |
34 | |
35 ~ExtensionInstallCheckerForTest() override {} | |
36 | |
37 bool is_async() const { return is_async_; } | |
38 void set_is_async(bool is_async) { is_async_ = is_async; } | |
39 | |
40 private: | |
41 // Whether to run the requirements and blacklist checks asynchronously, as | |
42 // they often do in ExtensionInstallChecker. | |
43 bool is_async_ = false; | |
44 }; | |
45 | |
46 class CheckObserver { | |
47 public: | |
48 CheckObserver() : result_(0), call_count_(0) {} | |
49 | |
50 int result() const { return result_; } | |
51 int call_count() const { return call_count_; } | |
52 | |
53 void OnChecksComplete(int checks_failed) { | |
54 result_ = checks_failed; | |
55 ++call_count_; | |
56 } | |
57 | |
58 void Wait() { | |
59 if (call_count_) | |
60 return; | |
61 | |
62 base::RunLoop().RunUntilIdle(); | |
63 } | |
64 | |
65 private: | |
66 int result_; | |
67 int call_count_; | |
68 }; | |
69 | |
70 class ExtensionInstallCheckerTest : public testing::Test { | |
71 public: | |
72 ExtensionInstallCheckerTest() {} | |
73 ~ExtensionInstallCheckerTest() override {} | |
74 | |
75 void SetBlacklistError(ExtensionInstallCheckerForTest* checker, | |
76 PreloadCheck::Error error) { | |
77 auto blacklist_check = base::MakeUnique<PreloadCheckStub>(); | |
78 blacklist_check->set_is_async(checker->is_async()); | |
79 if (error != PreloadCheck::NONE) | |
80 blacklist_check->AddError(error); | |
81 checker->SetBlacklistCheckForTesting(std::move(blacklist_check)); | |
82 } | |
83 | |
84 void SetPolicyError(ExtensionInstallCheckerForTest* checker, | |
85 PreloadCheck::Error error, | |
86 std::string message) { | |
87 // The policy check always runs synchronously. | |
88 auto policy_check = base::MakeUnique<PreloadCheckStub>(); | |
89 if (error != PreloadCheck::NONE) { | |
90 policy_check->AddError(error); | |
91 policy_check->set_error_message(base::UTF8ToUTF16(message)); | |
92 } | |
93 checker->SetPolicyCheckForTesting(std::move(policy_check)); | |
94 } | |
95 | |
96 void SetRequirementsError(ExtensionInstallCheckerForTest* checker, | |
97 PreloadCheck::Error error, | |
98 const std::string& message) { | |
99 auto requirements_check = base::MakeUnique<PreloadCheckStub>(); | |
100 requirements_check->set_is_async(checker->is_async()); | |
101 if (error != PreloadCheck::NONE) { | |
102 requirements_check->AddError(error); | |
103 requirements_check->set_error_message(base::UTF8ToUTF16(message)); | |
104 } | |
105 checker->SetRequirementsCheckForTesting(std::move(requirements_check)); | |
106 } | |
107 | |
108 protected: | |
109 void SetAllPass(ExtensionInstallCheckerForTest* checker) { | |
110 SetBlacklistError(checker, PreloadCheck::NONE); | |
111 SetPolicyError(checker, PreloadCheck::NONE, ""); | |
112 SetRequirementsError(checker, PreloadCheck::NONE, ""); | |
113 } | |
114 | |
115 void SetAllErrors(ExtensionInstallCheckerForTest* checker) { | |
116 SetBlacklistError(checker, kBlacklistError); | |
117 SetPolicyError(checker, PreloadCheck::DISALLOWED_BY_POLICY, | |
118 kDummyPolicyError); | |
119 SetRequirementsError(checker, PreloadCheck::NPAPI_NOT_SUPPORTED, | |
120 kDummyRequirementsError); | |
121 } | |
122 | |
123 void ExpectRequirementsPass(const ExtensionInstallCheckerForTest& checker) { | |
124 EXPECT_EQ(base::string16(), checker.requirements_error_message()); | |
125 } | |
126 | |
127 void ExpectRequirementsError(const char* expected_error, | |
128 const ExtensionInstallCheckerForTest& checker) { | |
129 EXPECT_EQ(base::UTF8ToUTF16(expected_error), | |
130 checker.requirements_error_message()); | |
131 } | |
132 | |
133 void ExpectRequirementsError(const ExtensionInstallCheckerForTest& checker) { | |
134 ExpectRequirementsError(kDummyRequirementsError, checker); | |
135 } | |
136 | |
137 void ExpectBlacklistPass(const ExtensionInstallCheckerForTest& checker) { | |
138 EXPECT_EQ(PreloadCheck::NONE, checker.blacklist_error()); | |
139 } | |
140 | |
141 void ExpectBlacklistError(const ExtensionInstallCheckerForTest& checker) { | |
142 EXPECT_EQ(kBlacklistError, checker.blacklist_error()); | |
143 } | |
144 | |
145 void ExpectPolicyPass(const ExtensionInstallCheckerForTest& checker) { | |
146 EXPECT_TRUE(checker.policy_error().empty()); | |
147 } | |
148 | |
149 void ExpectPolicyError(const char* expected_error, | |
150 const ExtensionInstallCheckerForTest& checker) { | |
151 EXPECT_FALSE(checker.policy_error().empty()); | |
152 EXPECT_EQ(base::UTF8ToUTF16(expected_error), checker.policy_error()); | |
153 } | |
154 | |
155 void ExpectPolicyError(const ExtensionInstallCheckerForTest& checker) { | |
156 ExpectPolicyError(kDummyPolicyError, checker); | |
157 } | |
158 | |
159 void RunChecker(ExtensionInstallCheckerForTest* checker, | |
160 int expected_result) { | |
161 CheckObserver observer; | |
162 checker->Start(base::Bind(&CheckObserver::OnChecksComplete, | |
163 base::Unretained(&observer))); | |
164 observer.Wait(); | |
165 | |
166 EXPECT_FALSE(checker->is_running()); | |
167 EXPECT_EQ(expected_result, observer.result()); | |
168 EXPECT_EQ(1, observer.call_count()); | |
169 } | |
170 | |
171 void DoRunAllChecksPass(ExtensionInstallCheckerForTest* checker) { | |
172 SetAllPass(checker); | |
173 RunChecker(checker, | |
174 0); | |
175 | |
176 ExpectRequirementsPass(*checker); | |
177 ExpectPolicyPass(*checker); | |
178 ExpectBlacklistPass(*checker); | |
179 } | |
180 | |
181 void DoRunAllChecksFail(ExtensionInstallCheckerForTest* checker) { | |
182 SetAllErrors(checker); | |
183 RunChecker(checker, | |
184 ExtensionInstallChecker::CHECK_ALL); | |
185 | |
186 ExpectRequirementsError(*checker); | |
187 ExpectPolicyError(*checker); | |
188 ExpectBlacklistError(*checker); | |
189 } | |
190 | |
191 void DoRunSubsetOfChecks(int checks_to_run) { | |
192 ExtensionInstallCheckerForTest sync_checker(checks_to_run, | |
193 /*fail_fast=*/false); | |
194 ExtensionInstallCheckerForTest async_checker(checks_to_run, | |
195 /*fail_fast=*/false); | |
196 async_checker.set_is_async(true); | |
197 | |
198 for (auto* checker : {&sync_checker, &async_checker}) { | |
199 SetAllErrors(checker); | |
200 RunChecker(checker, checks_to_run); | |
201 | |
202 if (checks_to_run & ExtensionInstallChecker::CHECK_REQUIREMENTS) | |
203 ExpectRequirementsError(*checker); | |
204 else | |
205 ExpectRequirementsPass(*checker); | |
206 | |
207 if (checks_to_run & ExtensionInstallChecker::CHECK_MANAGEMENT_POLICY) | |
208 ExpectPolicyError(*checker); | |
209 else | |
210 ExpectPolicyPass(*checker); | |
211 | |
212 if (checks_to_run & ExtensionInstallChecker::CHECK_BLACKLIST) | |
213 ExpectBlacklistError(*checker); | |
214 else | |
215 ExpectBlacklistPass(*checker); | |
216 } | |
217 } | |
218 | |
219 private: | |
220 // A message loop is required for the asynchronous tests. | |
221 base::MessageLoop message_loop; | |
222 }; | |
223 | |
224 // Test the case where all tests pass. | |
225 TEST_F(ExtensionInstallCheckerTest, AllSucceeded) { | |
226 ExtensionInstallCheckerForTest sync_checker( | |
227 ExtensionInstallChecker::CHECK_ALL, /*fail_fast=*/false); | |
228 DoRunAllChecksPass(&sync_checker); | |
229 | |
230 ExtensionInstallCheckerForTest async_checker( | |
231 ExtensionInstallChecker::CHECK_ALL, /*fail_fast=*/false); | |
232 async_checker.set_is_async(true); | |
233 DoRunAllChecksPass(&async_checker); | |
234 } | |
235 | |
236 // Test the case where all tests fail. | |
237 TEST_F(ExtensionInstallCheckerTest, AllFailed) { | |
238 ExtensionInstallCheckerForTest sync_checker( | |
239 ExtensionInstallChecker::CHECK_ALL, /*fail_fast=*/false); | |
240 DoRunAllChecksFail(&sync_checker); | |
241 | |
242 ExtensionInstallCheckerForTest async_checker( | |
243 ExtensionInstallChecker::CHECK_ALL, /*fail_fast=*/false); | |
244 async_checker.set_is_async(true); | |
245 DoRunAllChecksFail(&async_checker); | |
246 } | |
247 | |
248 // Test running only a subset of tests. | |
249 TEST_F(ExtensionInstallCheckerTest, RunSubsetOfChecks) { | |
250 DoRunSubsetOfChecks(ExtensionInstallChecker::CHECK_MANAGEMENT_POLICY | | |
251 ExtensionInstallChecker::CHECK_REQUIREMENTS); | |
252 DoRunSubsetOfChecks(ExtensionInstallChecker::CHECK_BLACKLIST | | |
253 ExtensionInstallChecker::CHECK_REQUIREMENTS); | |
254 DoRunSubsetOfChecks(ExtensionInstallChecker::CHECK_BLACKLIST); | |
255 } | |
256 | |
257 // Test fail fast with synchronous callbacks. | |
258 TEST_F(ExtensionInstallCheckerTest, FailFastSync) { | |
259 // This test assumes some internal knowledge of the implementation - that | |
260 // the policy check runs first. | |
261 { | |
262 ExtensionInstallCheckerForTest checker(ExtensionInstallChecker::CHECK_ALL, | |
263 /*fail_fast=*/true); | |
264 SetAllErrors(&checker); | |
265 RunChecker(&checker, ExtensionInstallChecker::CHECK_MANAGEMENT_POLICY); | |
266 | |
267 ExpectRequirementsPass(checker); | |
268 ExpectPolicyError(checker); | |
269 ExpectBlacklistPass(checker); | |
270 } | |
271 | |
272 { | |
273 ExtensionInstallCheckerForTest checker( | |
274 ExtensionInstallChecker::CHECK_REQUIREMENTS | | |
275 ExtensionInstallChecker::CHECK_BLACKLIST, | |
276 /*fail_fast=*/true); | |
277 SetAllErrors(&checker); | |
278 RunChecker(&checker, ExtensionInstallChecker::CHECK_REQUIREMENTS); | |
279 | |
280 ExpectRequirementsError(checker); | |
281 ExpectPolicyPass(checker); | |
282 ExpectBlacklistPass(checker); | |
283 } | |
284 } | |
285 | |
286 // Test fail fast with asynchronous callbacks. | |
287 TEST_F(ExtensionInstallCheckerTest, FailFastAsync) { | |
288 // This test assumes some internal knowledge of the implementation - that | |
289 // the requirements check runs before the blacklist check. Both checks should | |
290 // be called, but the requirements check callback arrives first and the | |
291 // blacklist result will be discarded. | |
292 ExtensionInstallCheckerForTest checker(ExtensionInstallChecker::CHECK_ALL, | |
293 /*fail_fast=*/true); | |
294 checker.set_is_async(true); | |
295 SetAllErrors(&checker); | |
296 | |
297 // The policy check is synchronous and needs to pass for the other tests to | |
298 // run. | |
299 SetPolicyError(&checker, PreloadCheck::NONE, ""); | |
300 | |
301 RunChecker(&checker, | |
302 ExtensionInstallChecker::CHECK_REQUIREMENTS); | |
303 | |
304 ExpectRequirementsError(checker); | |
305 ExpectPolicyPass(checker); | |
306 ExpectBlacklistPass(checker); | |
307 } | |
308 | |
309 } // namespace extensions | |
OLD | NEW |