blob: 71ba11aed88e22209f31e3e79a351141c38823e6 [file] [log] [blame]
Minh X. Nguyen5c83226102018-04-19 16:10:251// Copyright 2018 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/command_line.h"
Sorin Jianu55587d32018-11-14 21:43:276#include "base/json/json_reader.h"
Minh X. Nguyen5c83226102018-04-19 16:10:257#include "base/run_loop.h"
Lei Zhangfe5b86932019-02-01 17:26:598#include "base/strings/stringprintf.h"
John Abd-El-Malek1a9c36072018-08-14 03:09:539#include "base/test/bind_test_util.h"
Devlin Cronin15291e9c2018-06-07 21:37:4810#include "base/test/metrics/histogram_tester.h"
Gabriel Charettec7108742019-08-23 03:31:4011#include "base/test/task_environment.h"
Minh X. Nguyen5c83226102018-04-19 16:10:2512#include "chrome/browser/extensions/content_verifier_test_utils.h"
13#include "chrome/browser/extensions/extension_management_test_util.h"
14#include "chrome/browser/extensions/extension_service.h"
15#include "chrome/browser/extensions/updater/chrome_update_client_config.h"
16#include "chrome/browser/extensions/updater/extension_update_client_base_browsertest.h"
17#include "chrome/browser/extensions/updater/extension_updater.h"
18#include "chrome/common/chrome_switches.h"
19#include "components/policy/core/browser/browser_policy_connector.h"
20#include "components/policy/core/common/mock_configuration_policy_provider.h"
Sorin Jianu86ee558e2019-02-18 17:01:5021#include "components/update_client/net/url_loader_post_interceptor.h"
Minh X. Nguyenb3d3db32018-06-04 22:59:5622#include "content/public/test/browser_test_utils.h"
Minh X. Nguyen5c83226102018-04-19 16:10:2523#include "extensions/browser/content_verifier.h"
24#include "extensions/browser/extension_registry.h"
25#include "extensions/browser/external_install_info.h"
26#include "extensions/browser/mock_external_provider.h"
27#include "extensions/browser/test_extension_registry_observer.h"
28#include "extensions/browser/updater/extension_downloader.h"
29#include "extensions/browser/updater/manifest_fetch_data.h"
Minh X. Nguyenb3d3db32018-06-04 22:59:5630#include "extensions/common/extension_updater_uma.h"
Minh X. Nguyen5c83226102018-04-19 16:10:2531#include "extensions/common/extension_urls.h"
Minh X. Nguyen5c83226102018-04-19 16:10:2532
33namespace extensions {
34
35namespace {
36
Joshua Pawlickia3314d3c2018-08-22 17:14:3537const char kExtensionId[] = "aohghmighlieiainnegkcijnfilokake";
Minh X. Nguyen5c83226102018-04-19 16:10:2538
39using UpdateClientEvents = update_client::UpdateClient::Observer::Events;
40
41} // namespace
42
Joshua Pawlicki8ac39322019-04-04 21:22:4643class UpdateServiceTest : public ExtensionUpdateClientBaseTest {
Minh X. Nguyen5c83226102018-04-19 16:10:2544 public:
Joshua Pawlicki8ac39322019-04-04 21:22:4645 UpdateServiceTest() : ExtensionUpdateClientBaseTest() {}
Minh X. Nguyen5c83226102018-04-19 16:10:2546 ~UpdateServiceTest() override {}
47
48 void SetUpCommandLine(base::CommandLine* command_line) override {
49 ExtensionUpdateClientBaseTest::SetUpCommandLine(command_line);
50 command_line->AppendSwitchASCII(
51 switches::kExtensionContentVerification,
52 switches::kExtensionContentVerificationEnforce);
53 }
54
55 bool ShouldEnableContentVerification() override { return true; }
56};
57
Joshua Pawlicki8ac39322019-04-04 21:22:4658IN_PROC_BROWSER_TEST_F(UpdateServiceTest, NoUpdate) {
Minh X. Nguyen5c83226102018-04-19 16:10:2559 // Verify that UpdateService runs correctly when there's no update.
60 base::ScopedAllowBlockingForTesting allow_io;
Minh X. Nguyenb3d3db32018-06-04 22:59:5661 base::HistogramTester histogram_tester;
Minh X. Nguyen5c83226102018-04-19 16:10:2562
63 // Mock a no-update response.
Joshua Pawlicki8ac39322019-04-04 21:22:4664 ASSERT_TRUE(update_interceptor_->ExpectRequest(
65 std::make_unique<update_client::PartialMatch>(R"("updatecheck":{)"),
66 test_data_dir_.AppendASCII("updater/updatecheck_reply_noupdate_1.json")));
Minh X. Nguyen5c83226102018-04-19 16:10:2567
68 const base::FilePath crx_path = test_data_dir_.AppendASCII("updater/v1.crx");
69 const Extension* extension =
70 InstallExtension(crx_path, 1, Manifest::EXTERNAL_POLICY_DOWNLOAD);
71 ASSERT_TRUE(extension);
72 EXPECT_EQ(kExtensionId, extension->id());
73
74 extensions::ExtensionUpdater::CheckParams params;
75 params.ids = {kExtensionId};
Minh X. Nguyen722b9682018-04-25 21:46:4876 extension_service()->updater()->CheckNow(std::move(params));
Minh X. Nguyen5c83226102018-04-19 16:10:2577
Minh X. Nguyenb3d3db32018-06-04 22:59:5678 // UpdateService should emit a not-updated event.
Minh X. Nguyen5c83226102018-04-19 16:10:2579 EXPECT_EQ(UpdateClientEvents::COMPONENT_NOT_UPDATED,
80 WaitOnComponentUpdaterCompleteEvent(kExtensionId));
81
Minh X. Nguyenb3d3db32018-06-04 22:59:5682 content::FetchHistogramsFromChildProcesses();
Minh X. Nguyen42c0d702018-06-13 18:23:3583 EXPECT_THAT(histogram_tester.GetAllSamples(
84 "Extensions.ExtensionUpdaterRawUpdateCalls"),
85 testing::ElementsAre(base::Bucket(1, 1)));
Minh X. Nguyenb3d3db32018-06-04 22:59:5686 EXPECT_THAT(
87 histogram_tester.GetAllSamples("Extensions.ExtensionUpdaterUpdateCalls"),
88 testing::ElementsAre(base::Bucket(1, 1)));
89 EXPECT_THAT(
90 histogram_tester.GetAllSamples(
91 "Extensions.ExtensionUpdaterUpdateResults"),
92 testing::ElementsAre(base::Bucket(
93 static_cast<int>(ExtensionUpdaterUpdateResult::NO_UPDATE), 1)));
94 histogram_tester.ExpectTotalCount(
95 "Extensions.UnifiedExtensionUpdaterUpdateCheckErrors", 0);
96
Minh X. Nguyen5c83226102018-04-19 16:10:2597 ASSERT_EQ(1, update_interceptor_->GetCount())
98 << update_interceptor_->GetRequestsAsString();
99
100 // No update, thus no download nor ping activities.
John Abd-El-Malek1a9c36072018-08-14 03:09:53101 EXPECT_EQ(0, get_interceptor_count());
Minh X. Nguyen5c83226102018-04-19 16:10:25102 EXPECT_EQ(0, ping_interceptor_->GetCount())
103 << ping_interceptor_->GetRequestsAsString();
104
105 const std::string update_request =
Antonio Gomesb6162502018-06-28 20:21:55106 std::get<0>(update_interceptor_->GetRequests()[0]);
Lei Zhange8d7e9822019-02-20 05:40:44107 const auto root = base::JSONReader::Read(update_request);
108 ASSERT_TRUE(root);
Sorin Jianu55587d32018-11-14 21:43:27109 const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0];
110 EXPECT_EQ(kExtensionId, app.FindKey("appid")->GetString());
111 EXPECT_EQ("0.10", app.FindKey("version")->GetString());
112 EXPECT_TRUE(app.FindKey("enabled")->GetBool());
Minh X. Nguyen5c83226102018-04-19 16:10:25113}
114
Joshua Pawlicki8ac39322019-04-04 21:22:46115IN_PROC_BROWSER_TEST_F(UpdateServiceTest, UpdateCheckError) {
Minh X. Nguyenb3d3db32018-06-04 22:59:56116 // Verify that UpdateService works correctly when there's an error in the
117 // update check phase.
118 base::ScopedAllowBlockingForTesting allow_io;
119 base::HistogramTester histogram_tester;
120
121 // Mock an update check error.
Sorin Jianu55587d32018-11-14 21:43:27122 ASSERT_TRUE(update_interceptor_->ExpectRequest(
123 std::make_unique<update_client::PartialMatch>(R"("updatecheck":{)"),
124 net::HTTP_FORBIDDEN));
Minh X. Nguyenb3d3db32018-06-04 22:59:56125
126 const base::FilePath crx_path = test_data_dir_.AppendASCII("updater/v1.crx");
127 const Extension* extension =
128 InstallExtension(crx_path, 1, Manifest::EXTERNAL_POLICY_DOWNLOAD);
129 ASSERT_TRUE(extension);
130 EXPECT_EQ(kExtensionId, extension->id());
131
132 extensions::ExtensionUpdater::CheckParams params;
133 params.ids = {kExtensionId};
134 extension_service()->updater()->CheckNow(std::move(params));
135
136 // UpdateService should emit an error update event.
137 EXPECT_EQ(UpdateClientEvents::COMPONENT_UPDATE_ERROR,
138 WaitOnComponentUpdaterCompleteEvent(kExtensionId));
139
140 content::FetchHistogramsFromChildProcesses();
141 EXPECT_THAT(
142 histogram_tester.GetAllSamples("Extensions.ExtensionUpdaterUpdateCalls"),
143 testing::ElementsAre(base::Bucket(1, 1)));
Minh X. Nguyen42c0d702018-06-13 18:23:35144 EXPECT_THAT(histogram_tester.GetAllSamples(
145 "Extensions.ExtensionUpdaterRawUpdateCalls"),
146 testing::ElementsAre(base::Bucket(1, 1)));
Minh X. Nguyenb3d3db32018-06-04 22:59:56147 EXPECT_THAT(
148 histogram_tester.GetAllSamples(
149 "Extensions.ExtensionUpdaterUpdateResults"),
150 testing::ElementsAre(base::Bucket(
151 static_cast<int>(ExtensionUpdaterUpdateResult::UPDATE_CHECK_ERROR),
152 1)));
153 EXPECT_THAT(histogram_tester.GetAllSamples(
154 "Extensions.UnifiedExtensionUpdaterUpdateCheckErrors"),
155 testing::ElementsAre(base::Bucket(403, 1)));
156
157 ASSERT_EQ(1, update_interceptor_->GetCount())
158 << update_interceptor_->GetRequestsAsString();
159
160 // Error, thus no download nor ping activities.
John Abd-El-Malek1a9c36072018-08-14 03:09:53161 EXPECT_EQ(0, get_interceptor_count());
Minh X. Nguyenb3d3db32018-06-04 22:59:56162 EXPECT_EQ(0, ping_interceptor_->GetCount())
163 << ping_interceptor_->GetRequestsAsString();
164
165 const std::string update_request =
Antonio Gomesb6162502018-06-28 20:21:55166 std::get<0>(update_interceptor_->GetRequests()[0]);
Lei Zhange8d7e9822019-02-20 05:40:44167 const auto root = base::JSONReader::Read(update_request);
168 ASSERT_TRUE(root);
Sorin Jianu55587d32018-11-14 21:43:27169 const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0];
170 EXPECT_EQ(kExtensionId, app.FindKey("appid")->GetString());
171 EXPECT_EQ("0.10", app.FindKey("version")->GetString());
172 EXPECT_TRUE(app.FindKey("enabled")->GetBool());
Minh X. Nguyenb3d3db32018-06-04 22:59:56173}
174
Joshua Pawlicki8ac39322019-04-04 21:22:46175IN_PROC_BROWSER_TEST_F(UpdateServiceTest, TwoUpdateCheckErrors) {
Minh X. Nguyenb3d3db32018-06-04 22:59:56176 // Verify that the UMA counters are emitted properly when there are 2 update
177 // checks with different number of extensions, both of which result in errors.
178 base::ScopedAllowBlockingForTesting allow_io;
179 base::HistogramTester histogram_tester;
180
181 // Mock update check errors.
Sorin Jianu55587d32018-11-14 21:43:27182 ASSERT_TRUE(update_interceptor_->ExpectRequest(
183 std::make_unique<update_client::PartialMatch>(R"("updatecheck":{)"),
184 net::HTTP_NOT_MODIFIED));
185 ASSERT_TRUE(update_interceptor_->ExpectRequest(
186 std::make_unique<update_client::PartialMatch>(R"("updatecheck":{)"),
187 net::HTTP_USE_PROXY));
Minh X. Nguyenb3d3db32018-06-04 22:59:56188
189 const base::FilePath crx_path1 = test_data_dir_.AppendASCII("updater/v1.crx");
190 const base::FilePath crx_path2 = test_data_dir_.AppendASCII("updater/v2.crx");
191 const Extension* extension1 =
192 InstallExtension(crx_path1, 1, Manifest::EXTERNAL_POLICY_DOWNLOAD);
193 const Extension* extension2 =
194 InstallExtension(crx_path2, 1, Manifest::EXTERNAL_POLICY_DOWNLOAD);
195 ASSERT_TRUE(extension1 && extension2);
196
197 extensions::ExtensionUpdater::CheckParams params;
198
199 base::RunLoop run_loop1;
200 params.ids = {extension1->id(), extension2->id()};
201 params.callback = run_loop1.QuitClosure();
202 extension_service()->updater()->CheckNow(std::move(params));
203 run_loop1.Run();
204
205 base::RunLoop run_loop2;
206 params.ids = {extension1->id()};
207 params.callback = run_loop2.QuitClosure();
208 extension_service()->updater()->CheckNow(std::move(params));
209 run_loop2.Run();
210
211 content::FetchHistogramsFromChildProcesses();
Minh X. Nguyen42c0d702018-06-13 18:23:35212 EXPECT_THAT(histogram_tester.GetAllSamples(
213 "Extensions.ExtensionUpdaterRawUpdateCalls"),
214 testing::ElementsAre(base::Bucket(1, 1), base::Bucket(2, 1)));
Minh X. Nguyenb3d3db32018-06-04 22:59:56215 EXPECT_THAT(
216 histogram_tester.GetAllSamples("Extensions.ExtensionUpdaterUpdateCalls"),
217 testing::ElementsAre(base::Bucket(1, 1), base::Bucket(2, 1)));
218 EXPECT_THAT(
219 histogram_tester.GetAllSamples(
220 "Extensions.ExtensionUpdaterUpdateResults"),
221 testing::ElementsAre(base::Bucket(
222 static_cast<int>(ExtensionUpdaterUpdateResult::UPDATE_CHECK_ERROR),
223 3)));
224 EXPECT_THAT(histogram_tester.GetAllSamples(
225 "Extensions.UnifiedExtensionUpdaterUpdateCheckErrors"),
226 testing::ElementsAre(base::Bucket(304, 2), base::Bucket(305, 1)));
227
228 ASSERT_EQ(2, update_interceptor_->GetCount())
229 << update_interceptor_->GetRequestsAsString();
230
231 // Error, thus no download nor ping activities.
John Abd-El-Malek1a9c36072018-08-14 03:09:53232 EXPECT_EQ(0, get_interceptor_count());
Minh X. Nguyenb3d3db32018-06-04 22:59:56233 EXPECT_EQ(0, ping_interceptor_->GetCount())
234 << ping_interceptor_->GetRequestsAsString();
235}
236
Joshua Pawlicki8ac39322019-04-04 21:22:46237IN_PROC_BROWSER_TEST_F(UpdateServiceTest, SuccessfulUpdate) {
Minh X. Nguyen5c83226102018-04-19 16:10:25238 base::ScopedAllowBlockingForTesting allow_io;
Minh X. Nguyenb3d3db32018-06-04 22:59:56239 base::HistogramTester histogram_tester;
Minh X. Nguyen5c83226102018-04-19 16:10:25240
241 // Mock an update response.
Sorin Jianu55587d32018-11-14 21:43:27242 const base::FilePath update_response =
243 test_data_dir_.AppendASCII("updater/updatecheck_reply_update_1.json");
244 const base::FilePath ping_response =
245 test_data_dir_.AppendASCII("updater/ping_reply_1.json");
246 ASSERT_TRUE(update_interceptor_->ExpectRequest(
247 std::make_unique<update_client::PartialMatch>(R"("updatecheck":{)"),
248 update_response));
249 ASSERT_TRUE(ping_interceptor_->ExpectRequest(
250 std::make_unique<update_client::PartialMatch>(R"("eventtype":)"),
251 ping_response));
Minh X. Nguyen5c83226102018-04-19 16:10:25252
Sorin Jianu55587d32018-11-14 21:43:27253 const base::FilePath crx_path = test_data_dir_.AppendASCII("updater/v1.crx");
John Abd-El-Malek1a9c36072018-08-14 03:09:53254 set_interceptor_hook(base::BindLambdaForTesting(
255 [&](content::URLLoaderInterceptor::RequestParams* params) {
256 if (params->url_request.url.path() != "/download/v1.crx")
257 return false;
258
259 content::URLLoaderInterceptor::WriteResponse(crx_path,
260 params->client.get());
261 return true;
262 }));
Minh X. Nguyen5c83226102018-04-19 16:10:25263
264 const Extension* extension =
265 InstallExtension(crx_path, 1, Manifest::EXTERNAL_POLICY_DOWNLOAD);
266 ASSERT_TRUE(extension);
267 EXPECT_EQ(kExtensionId, extension->id());
268
269 base::RunLoop run_loop;
270
271 extensions::ExtensionUpdater::CheckParams params;
272 params.ids = {kExtensionId};
Minh X. Nguyen722b9682018-04-25 21:46:48273 params.callback = run_loop.QuitClosure();
274 extension_service()->updater()->CheckNow(std::move(params));
Minh X. Nguyen5c83226102018-04-19 16:10:25275
276 EXPECT_EQ(UpdateClientEvents::COMPONENT_UPDATED,
277 WaitOnComponentUpdaterCompleteEvent(kExtensionId));
278
279 run_loop.Run();
280
Minh X. Nguyenb3d3db32018-06-04 22:59:56281 content::FetchHistogramsFromChildProcesses();
Hajime Hoshic7a8a7c42019-01-09 00:58:03282 EXPECT_THAT(histogram_tester.GetAllSamples(
283 "Extensions.ExtensionUpdaterRawUpdateCalls"),
284 testing::ElementsAre(base::Bucket(1, 1)));
Minh X. Nguyenb3d3db32018-06-04 22:59:56285 EXPECT_THAT(
286 histogram_tester.GetAllSamples("Extensions.ExtensionUpdaterUpdateCalls"),
287 testing::ElementsAre(base::Bucket(1, 1)));
288 EXPECT_THAT(
289 histogram_tester.GetAllSamples(
290 "Extensions.ExtensionUpdaterUpdateResults"),
291 testing::ElementsAre(base::Bucket(
292 static_cast<int>(ExtensionUpdaterUpdateResult::UPDATE_SUCCESS), 1)));
293 histogram_tester.ExpectTotalCount(
294 "Extensions.UnifiedExtensionUpdaterUpdateCheckErrors", 0);
295
Minh X. Nguyen5c83226102018-04-19 16:10:25296 ASSERT_EQ(1, update_interceptor_->GetCount())
297 << update_interceptor_->GetRequestsAsString();
John Abd-El-Malek1a9c36072018-08-14 03:09:53298 EXPECT_EQ(1, get_interceptor_count());
Minh X. Nguyen5c83226102018-04-19 16:10:25299
300 const std::string update_request =
Antonio Gomesb6162502018-06-28 20:21:55301 std::get<0>(update_interceptor_->GetRequests()[0]);
Lei Zhange8d7e9822019-02-20 05:40:44302 const auto root = base::JSONReader::Read(update_request);
303 ASSERT_TRUE(root);
Sorin Jianu55587d32018-11-14 21:43:27304 const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0];
305 EXPECT_EQ(kExtensionId, app.FindKey("appid")->GetString());
306 EXPECT_EQ("0.10", app.FindKey("version")->GetString());
307 EXPECT_TRUE(app.FindKey("enabled")->GetBool());
Minh X. Nguyen5c83226102018-04-19 16:10:25308}
309
Joshua Pawlicki8ac39322019-04-04 21:22:46310IN_PROC_BROWSER_TEST_F(UpdateServiceTest, PolicyCorrupted) {
Minh X. Nguyen5c83226102018-04-19 16:10:25311 base::ScopedAllowBlockingForTesting allow_io;
312
313 ExtensionSystem* system = ExtensionSystem::Get(profile());
314 ExtensionService* service = extension_service();
315
Sorin Jianu55587d32018-11-14 21:43:27316 const base::FilePath update_response =
317 test_data_dir_.AppendASCII("updater/updatecheck_reply_update_1.json");
318 const base::FilePath ping_response =
319 test_data_dir_.AppendASCII("updater/ping_reply_1.json");
320 ASSERT_TRUE(update_interceptor_->ExpectRequest(
321 std::make_unique<update_client::PartialMatch>(R"("updatecheck":{)"),
322 update_response));
323 ASSERT_TRUE(ping_interceptor_->ExpectRequest(
324 std::make_unique<update_client::PartialMatch>(R"("eventtype":)"),
325 ping_response));
Minh X. Nguyen5c83226102018-04-19 16:10:25326
Sorin Jianu55587d32018-11-14 21:43:27327 const base::FilePath crx_path = test_data_dir_.AppendASCII("updater/v1.crx");
John Abd-El-Malek1a9c36072018-08-14 03:09:53328 set_interceptor_hook(base::BindLambdaForTesting(
329 [&](content::URLLoaderInterceptor::RequestParams* params) {
330 if (params->url_request.url.path() != "/download/v1.crx")
331 return false;
332
333 content::URLLoaderInterceptor::WriteResponse(crx_path,
334 params->client.get());
335 return true;
336 }));
Minh X. Nguyen5c83226102018-04-19 16:10:25337
338 // Setup fake policy and update check objects.
339 content_verifier_test::ForceInstallProvider policy(kExtensionId);
340 system->management_policy()->RegisterProvider(&policy);
341 auto external_provider = std::make_unique<MockExternalProvider>(
342 service, Manifest::EXTERNAL_POLICY_DOWNLOAD);
343 external_provider->UpdateOrAddExtension(
344 std::make_unique<ExternalInstallInfoUpdateUrl>(
345 kExtensionId, std::string() /* install_parameter */,
346 extension_urls::GetWebstoreUpdateUrl(),
347 Manifest::EXTERNAL_POLICY_DOWNLOAD, 0 /* creation_flags */,
348 true /* mark_acknowledged */));
349 service->AddProviderForTesting(std::move(external_provider));
350
351 const Extension* extension =
352 InstallExtension(crx_path, 1, Manifest::EXTERNAL_POLICY_DOWNLOAD);
353 ASSERT_TRUE(extension);
354 EXPECT_EQ(kExtensionId, extension->id());
355
356 TestExtensionRegistryObserver registry_observer(
357 ExtensionRegistry::Get(profile()), kExtensionId);
358 ContentVerifier* verifier = system->content_verifier();
Oleg Davydov9b465ba2019-07-02 12:28:08359 verifier->VerifyFailedForTest(kExtensionId, ContentVerifyJob::HASH_MISMATCH);
Minh X. Nguyen5c83226102018-04-19 16:10:25360
361 // Make sure the extension first got disabled due to corruption.
362 EXPECT_TRUE(registry_observer.WaitForExtensionUnloaded());
363 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
364 int reasons = prefs->GetDisableReasons(kExtensionId);
365 EXPECT_TRUE(reasons & disable_reason::DISABLE_CORRUPTED);
366
367 // Make sure the extension then got re-installed, and that after reinstall it
368 // is no longer disabled due to corruption.
369 EXPECT_EQ(UpdateClientEvents::COMPONENT_UPDATED,
370 WaitOnComponentUpdaterCompleteEvent(kExtensionId));
371
372 reasons = prefs->GetDisableReasons(kExtensionId);
373 EXPECT_FALSE(reasons & disable_reason::DISABLE_CORRUPTED);
374
375 ASSERT_EQ(1, update_interceptor_->GetCount())
376 << update_interceptor_->GetRequestsAsString();
John Abd-El-Malek1a9c36072018-08-14 03:09:53377 EXPECT_EQ(1, get_interceptor_count());
Minh X. Nguyen5c83226102018-04-19 16:10:25378
379 // Make sure that the update check request is formed correctly when the
380 // extension is corrupted:
381 // - version="0.0.0.0"
382 // - installsource="reinstall"
Minh X. Nguyenfc16497e2018-04-24 16:05:35383 // - installedby="policy"
Minh X. Nguyen5c83226102018-04-19 16:10:25384 // - enabled="0"
385 // - <disabled reason="1024"/>
386 const std::string update_request =
Antonio Gomesb6162502018-06-28 20:21:55387 std::get<0>(update_interceptor_->GetRequests()[0]);
Lei Zhange8d7e9822019-02-20 05:40:44388 const auto root = base::JSONReader::Read(update_request);
389 ASSERT_TRUE(root);
Sorin Jianu55587d32018-11-14 21:43:27390 const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0];
391 EXPECT_EQ(kExtensionId, app.FindKey("appid")->GetString());
392 EXPECT_EQ("0.0.0.0", app.FindKey("version")->GetString());
393 EXPECT_EQ("reinstall", app.FindKey("installsource")->GetString());
394 EXPECT_EQ("policy", app.FindKey("installedby")->GetString());
395 EXPECT_FALSE(app.FindKey("enabled")->GetBool());
396 const auto& disabled = app.FindKey("disabled")->GetList()[0];
397 EXPECT_EQ(disable_reason::DISABLE_CORRUPTED,
398 disabled.FindKey("reason")->GetInt());
Minh X. Nguyen5c83226102018-04-19 16:10:25399}
400
Joshua Pawlicki8ac39322019-04-04 21:22:46401IN_PROC_BROWSER_TEST_F(UpdateServiceTest, UninstallExtensionWhileUpdating) {
Minh X. Nguyenad500fb2018-05-03 17:31:02402 // This test is to verify that the extension updater engine (update client)
403 // works correctly when an extension is uninstalled when the extension updater
404 // is in progress.
405 base::ScopedAllowBlockingForTesting allow_io;
406
407 const base::FilePath crx_path = test_data_dir_.AppendASCII("updater/v1.crx");
408
409 const Extension* extension =
410 InstallExtension(crx_path, 1, Manifest::EXTERNAL_POLICY_DOWNLOAD);
411 ASSERT_TRUE(extension);
412 EXPECT_EQ(kExtensionId, extension->id());
413
414 base::RunLoop run_loop;
415
416 extensions::ExtensionUpdater::CheckParams params;
417 params.ids = {kExtensionId};
418 params.callback = run_loop.QuitClosure();
419 extension_service()->updater()->CheckNow(std::move(params));
420
421 // Uninstall the extension right before the message loop is executed to
422 // emulate uninstalling an extension in the middle of an extension update.
423 extension_service()->UninstallExtension(
424 kExtensionId, extensions::UNINSTALL_REASON_COMPONENT_REMOVED, nullptr);
425
426 // Update client should issue an update error event for this extension.
427 ASSERT_EQ(UpdateClientEvents::COMPONENT_UPDATE_ERROR,
428 WaitOnComponentUpdaterCompleteEvent(kExtensionId));
429
430 run_loop.Run();
431
432 EXPECT_EQ(0, update_interceptor_->GetCount())
433 << update_interceptor_->GetRequestsAsString();
John Abd-El-Malek1a9c36072018-08-14 03:09:53434 EXPECT_EQ(0, get_interceptor_count());
Minh X. Nguyenad500fb2018-05-03 17:31:02435}
436
Sorin Jianu55587d32018-11-14 21:43:27437class PolicyUpdateServiceTest : public ExtensionUpdateClientBaseTest,
438 public testing::WithParamInterface<bool> {
Minh X. Nguyen5c83226102018-04-19 16:10:25439 public:
Joshua Pawlicki8ac39322019-04-04 21:22:46440 PolicyUpdateServiceTest() : ExtensionUpdateClientBaseTest() {}
Minh X. Nguyen5c83226102018-04-19 16:10:25441 ~PolicyUpdateServiceTest() override {}
442
443 void SetUpCommandLine(base::CommandLine* command_line) override {
444 ExtensionUpdateClientBaseTest::SetUpCommandLine(command_line);
445 command_line->AppendSwitchASCII(
446 switches::kExtensionContentVerification,
447 switches::kExtensionContentVerificationEnforce);
448 }
449
450 void SetUpInProcessBrowserTestFixture() override {
451 ExtensionUpdateClientBaseTest::SetUpInProcessBrowserTestFixture();
452
453 EXPECT_CALL(policy_provider_, IsInitializationComplete(testing::_))
454 .WillRepeatedly(testing::Return(true));
455
456 policy::BrowserPolicyConnector::SetPolicyProviderForTesting(
457 &policy_provider_);
Takashi Toyoshima52f24672019-03-05 05:36:36458 // ExtensionManagementPolicyUpdater requires a single-threaded context to
459 // call RunLoop::RunUntilIdle internally, and it isn't ready at this setup
460 // moment.
Gabriel Charette694c3c332019-08-19 14:53:05461 base::test::TaskEnvironment env;
Minh X. Nguyen5c83226102018-04-19 16:10:25462 ExtensionManagementPolicyUpdater management_policy(&policy_provider_);
463 management_policy.SetIndividualExtensionAutoInstalled(
464 id_, extension_urls::kChromeWebstoreUpdateURL, true /* forced */);
465
466 // The policy will force the new install of an extension, which the
467 // component updater doesn't support yet. We still rely on the old updater
468 // to install a new extension.
469 const base::FilePath crx_path =
470 test_data_dir_.AppendASCII("updater/v1.crx");
471 ExtensionDownloader::set_test_delegate(&downloader_);
472 downloader_.AddResponse(id_, "2", crx_path);
473 }
474
475 void SetUpNetworkInterceptors() override {
476 ExtensionUpdateClientBaseTest::SetUpNetworkInterceptors();
477
478 const base::FilePath crx_path =
479 test_data_dir_.AppendASCII("updater/v1.crx");
John Abd-El-Malek1a9c36072018-08-14 03:09:53480 set_interceptor_hook(base::BindLambdaForTesting(
481 [=](content::URLLoaderInterceptor::RequestParams* params) {
482 if (params->url_request.url.path() != "/download/v1.crx")
483 return false;
484
485 content::URLLoaderInterceptor::WriteResponse(crx_path,
486 params->client.get());
487 return true;
488 }));
Sorin Jianu55587d32018-11-14 21:43:27489 const base::FilePath update_response =
490 test_data_dir_.AppendASCII("updater/updatecheck_reply_update_1.json");
491 const base::FilePath ping_response =
492 test_data_dir_.AppendASCII("updater/ping_reply_1.json");
493
494 ASSERT_TRUE(update_interceptor_->ExpectRequest(
495 std::make_unique<update_client::PartialMatch>(R"("updatecheck":{)"),
496 update_response));
497 ASSERT_TRUE(update_interceptor_->ExpectRequest(
498 std::make_unique<update_client::PartialMatch>(R"("updatecheck":{)"),
499 update_response));
500 ASSERT_TRUE(update_interceptor_->ExpectRequest(
501 std::make_unique<update_client::PartialMatch>(R"("updatecheck":{)"),
502 update_response));
503 ASSERT_TRUE(update_interceptor_->ExpectRequest(
504 std::make_unique<update_client::PartialMatch>(R"("updatecheck":{)"),
505 update_response));
506 ASSERT_TRUE(ping_interceptor_->ExpectRequest(
507 std::make_unique<update_client::PartialMatch>(R"("eventtype":)"),
508 ping_response));
509 ASSERT_TRUE(ping_interceptor_->ExpectRequest(
510 std::make_unique<update_client::PartialMatch>(R"("eventtype":)"),
511 ping_response));
512 ASSERT_TRUE(ping_interceptor_->ExpectRequest(
513 std::make_unique<update_client::PartialMatch>(R"("eventtype":)"),
514 ping_response));
515 ASSERT_TRUE(ping_interceptor_->ExpectRequest(
516 std::make_unique<update_client::PartialMatch>(R"("eventtype":)"),
517 ping_response));
Minh X. Nguyen5c83226102018-04-19 16:10:25518 }
519
520 std::vector<GURL> GetUpdateUrls() const override {
Antonio Gomesb6162502018-06-28 20:21:55521 return {
522 https_server_for_update_.GetURL("/policy-updatehost/service/update")};
Minh X. Nguyen5c83226102018-04-19 16:10:25523 }
524
525 std::vector<GURL> GetPingUrls() const override {
Antonio Gomesb6162502018-06-28 20:21:55526 return {https_server_for_ping_.GetURL("/policy-pinghost/service/ping")};
Minh X. Nguyen5c83226102018-04-19 16:10:25527 }
528
529 protected:
530 // The id of the extension we want to have force-installed.
Joshua Pawlickia3314d3c2018-08-22 17:14:35531 std::string id_ = "aohghmighlieiainnegkcijnfilokake";
Minh X. Nguyen5c83226102018-04-19 16:10:25532
533 private:
534 policy::MockConfigurationPolicyProvider policy_provider_;
535 content_verifier_test::DownloaderTestDelegate downloader_;
536};
537
538// Tests that if CheckForExternalUpdates() fails, then we retry reinstalling
539// corrupted policy extensions. For example: if network is unavailable,
540// CheckForExternalUpdates() will fail.
Joshua Pawlicki8ac39322019-04-04 21:22:46541IN_PROC_BROWSER_TEST_F(PolicyUpdateServiceTest, FailedUpdateRetries) {
Minh X. Nguyen5c83226102018-04-19 16:10:25542 ExtensionRegistry* registry = ExtensionRegistry::Get(profile());
543 ExtensionService* service = extension_service();
544 ContentVerifier* verifier =
545 ExtensionSystem::Get(profile())->content_verifier();
546
547 // Wait for the extension to be installed by the policy we set up in
548 // SetUpInProcessBrowserTestFixture.
549 if (!registry->GetInstalledExtension(id_)) {
550 TestExtensionRegistryObserver registry_observer(registry, id_);
551 EXPECT_TRUE(registry_observer.WaitForExtensionInstalled());
552 }
553
554 content_verifier_test::DelayTracker delay_tracker;
555 service->set_external_updates_disabled_for_test(true);
556 TestExtensionRegistryObserver registry_observer(registry, id_);
Oleg Davydov9b465ba2019-07-02 12:28:08557 verifier->VerifyFailedForTest(id_, ContentVerifyJob::HASH_MISMATCH);
Minh X. Nguyen5c83226102018-04-19 16:10:25558 EXPECT_TRUE(registry_observer.WaitForExtensionUnloaded());
559
560 const std::vector<base::TimeDelta>& calls = delay_tracker.calls();
561 ASSERT_EQ(1u, calls.size());
562 EXPECT_EQ(base::TimeDelta(), delay_tracker.calls()[0]);
563
564 delay_tracker.Proceed();
565
566 // Remove the override and set ExtensionService to update again. The extension
567 // should be now installed.
568 service->set_external_updates_disabled_for_test(false);
569 delay_tracker.StopWatching();
570 delay_tracker.Proceed();
571
572 EXPECT_EQ(UpdateClientEvents::COMPONENT_UPDATED,
573 WaitOnComponentUpdaterCompleteEvent(id_));
574
575 ASSERT_EQ(1, update_interceptor_->GetCount())
576 << update_interceptor_->GetRequestsAsString();
John Abd-El-Malek1a9c36072018-08-14 03:09:53577 EXPECT_EQ(1, get_interceptor_count());
Minh X. Nguyen5c83226102018-04-19 16:10:25578
579 // Make sure that the update check request is formed correctly when the
580 // extension is corrupted:
581 // - version="0.0.0.0"
582 // - installsource="reinstall"
Minh X. Nguyenfc16497e2018-04-24 16:05:35583 // - installedby="policy"
Minh X. Nguyen5c83226102018-04-19 16:10:25584 // - enabled="0"
585 // - <disabled reason="1024"/>
586 const std::string update_request =
Antonio Gomesb6162502018-06-28 20:21:55587 std::get<0>(update_interceptor_->GetRequests()[0]);
Lei Zhange8d7e9822019-02-20 05:40:44588 const auto root = base::JSONReader::Read(update_request);
589 ASSERT_TRUE(root);
Sorin Jianu55587d32018-11-14 21:43:27590 const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0];
591 EXPECT_EQ(id_, app.FindKey("appid")->GetString());
592 EXPECT_EQ("0.0.0.0", app.FindKey("version")->GetString());
593 EXPECT_EQ("reinstall", app.FindKey("installsource")->GetString());
594 EXPECT_EQ("policy", app.FindKey("installedby")->GetString());
595 EXPECT_FALSE(app.FindKey("enabled")->GetBool());
596 const auto& disabled = app.FindKey("disabled")->GetList()[0];
597 EXPECT_EQ(disable_reason::DISABLE_CORRUPTED,
598 disabled.FindKey("reason")->GetInt());
Minh X. Nguyen5c83226102018-04-19 16:10:25599}
600
Joshua Pawlicki8ac39322019-04-04 21:22:46601IN_PROC_BROWSER_TEST_F(PolicyUpdateServiceTest, Backoff) {
Minh X. Nguyen5c83226102018-04-19 16:10:25602 ExtensionRegistry* registry = ExtensionRegistry::Get(profile());
603 ContentVerifier* verifier =
604 ExtensionSystem::Get(profile())->content_verifier();
605
606 // Wait for the extension to be installed by the policy we set up in
607 // SetUpInProcessBrowserTestFixture.
608 if (!registry->GetInstalledExtension(id_)) {
609 TestExtensionRegistryObserver registry_observer(registry, id_);
610 EXPECT_TRUE(registry_observer.WaitForExtensionInstalled());
611 }
612
613 // Setup to intercept reinstall action, so we can see what the delay would
614 // have been for the real action.
615 content_verifier_test::DelayTracker delay_tracker;
616
617 // Do 4 iterations of disabling followed by reinstall.
618 const size_t iterations = 4;
619 for (size_t i = 0; i < iterations; i++) {
620 TestExtensionRegistryObserver registry_observer(registry, id_);
Oleg Davydov9b465ba2019-07-02 12:28:08621 verifier->VerifyFailedForTest(id_, ContentVerifyJob::HASH_MISMATCH);
Minh X. Nguyen5c83226102018-04-19 16:10:25622 EXPECT_TRUE(registry_observer.WaitForExtensionUnloaded());
623 // Resolve the request to |delay_tracker|, so the reinstallation can
624 // proceed.
625 delay_tracker.Proceed();
626 EXPECT_EQ(UpdateClientEvents::COMPONENT_UPDATED,
627 WaitOnComponentUpdaterCompleteEvent(id_));
628 }
629
630 ASSERT_EQ(4, update_interceptor_->GetCount())
631 << update_interceptor_->GetRequestsAsString();
John Abd-El-Malek1a9c36072018-08-14 03:09:53632 EXPECT_EQ(4, get_interceptor_count());
Minh X. Nguyen5c83226102018-04-19 16:10:25633
634 const std::vector<base::TimeDelta>& calls = delay_tracker.calls();
635
636 // After |delay_tracker| resolves the 4 (|iterations|) reinstallation
637 // requests, it will get an additional request (right away) for retrying
638 // reinstallation.
639 // Note: the additional request in non-test environment will arrive with
640 // a (backoff) delay. But during test, |delay_tracker| issues the request
641 // immediately.
642 ASSERT_EQ(iterations, calls.size() - 1);
643 // Assert that the first reinstall action happened with a delay of 0, and
644 // then kept growing each additional time.
645 EXPECT_EQ(base::TimeDelta(), delay_tracker.calls()[0]);
646 for (size_t i = 1; i < delay_tracker.calls().size(); i++) {
647 EXPECT_LT(calls[i - 1], calls[i]);
648 }
649}
650
651// We want to test what happens at startup with a corroption-disabled policy
652// force installed extension. So we set that up in the PRE test here.
Joshua Pawlicki8ac39322019-04-04 21:22:46653IN_PROC_BROWSER_TEST_F(PolicyUpdateServiceTest, PRE_PolicyCorruptedOnStartup) {
Minh X. Nguyen5c83226102018-04-19 16:10:25654 // This is to not allow any corrupted resintall to proceed.
655 content_verifier_test::DelayTracker delay_tracker;
656 ExtensionRegistry* registry = ExtensionRegistry::Get(profile());
657 TestExtensionRegistryObserver registry_observer(registry, id_);
658
659 // Wait for the extension to be installed by policy we set up in
660 // SetUpInProcessBrowserTestFixture.
661 if (!registry->GetInstalledExtension(id_))
662 EXPECT_TRUE(registry_observer.WaitForExtensionInstalled());
663
664 // Simulate corruption of the extension so that we can test what happens
665 // at startup in the non-PRE test.
666 ContentVerifier* verifier =
667 ExtensionSystem::Get(profile())->content_verifier();
Oleg Davydov9b465ba2019-07-02 12:28:08668 verifier->VerifyFailedForTest(id_, ContentVerifyJob::HASH_MISMATCH);
Minh X. Nguyen5c83226102018-04-19 16:10:25669 EXPECT_TRUE(registry_observer.WaitForExtensionUnloaded());
670
671 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
672 int reasons = prefs->GetDisableReasons(id_);
673 EXPECT_TRUE(reasons & disable_reason::DISABLE_CORRUPTED);
674 EXPECT_EQ(1u, delay_tracker.calls().size());
675
676 EXPECT_EQ(0, update_interceptor_->GetCount())
677 << update_interceptor_->GetRequestsAsString();
John Abd-El-Malek1a9c36072018-08-14 03:09:53678 EXPECT_EQ(0, get_interceptor_count());
Minh X. Nguyen5c83226102018-04-19 16:10:25679}
680
681// Now actually test what happens on the next startup after the PRE test above.
Joshua Pawlicki8ac39322019-04-04 21:22:46682IN_PROC_BROWSER_TEST_F(PolicyUpdateServiceTest, PolicyCorruptedOnStartup) {
Minh X. Nguyen5c83226102018-04-19 16:10:25683 // Depdending on timing, the extension may have already been reinstalled
684 // between SetUpInProcessBrowserTestFixture and now (usually not during local
685 // testing on a developer machine, but sometimes on a heavily loaded system
686 // such as the build waterfall / trybots). If the reinstall didn't already
687 // happen, wait for it.
688
689 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
690 ExtensionRegistry* registry = ExtensionRegistry::Get(profile());
691 int disable_reasons = prefs->GetDisableReasons(id_);
692 if (disable_reasons & disable_reason::DISABLE_CORRUPTED) {
693 EXPECT_EQ(UpdateClientEvents::COMPONENT_UPDATED,
694 WaitOnComponentUpdaterCompleteEvent(id_));
695 disable_reasons = prefs->GetDisableReasons(id_);
696 }
697
698 EXPECT_FALSE(disable_reasons & disable_reason::DISABLE_CORRUPTED);
699 EXPECT_TRUE(registry->enabled_extensions().Contains(id_));
700
701 ASSERT_EQ(1, update_interceptor_->GetCount())
702 << update_interceptor_->GetRequestsAsString();
John Abd-El-Malek1a9c36072018-08-14 03:09:53703 EXPECT_EQ(1, get_interceptor_count());
Minh X. Nguyen5c83226102018-04-19 16:10:25704
705 const std::string update_request =
Antonio Gomesb6162502018-06-28 20:21:55706 std::get<0>(update_interceptor_->GetRequests()[0]);
Lei Zhange8d7e9822019-02-20 05:40:44707 const auto root = base::JSONReader::Read(update_request);
708 ASSERT_TRUE(root);
Sorin Jianu55587d32018-11-14 21:43:27709 const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0];
710 EXPECT_EQ(id_, app.FindKey("appid")->GetString());
711 EXPECT_EQ("0.0.0.0", app.FindKey("version")->GetString());
712 EXPECT_EQ("reinstall", app.FindKey("installsource")->GetString());
713 EXPECT_EQ("policy", app.FindKey("installedby")->GetString());
714 EXPECT_FALSE(app.FindKey("enabled")->GetBool());
715 const auto& disabled = app.FindKey("disabled")->GetList()[0];
716 EXPECT_EQ(disable_reason::DISABLE_CORRUPTED,
717 disabled.FindKey("reason")->GetInt());
Minh X. Nguyen5c83226102018-04-19 16:10:25718}
719
720} // namespace extensions