blob: 9a1a2a187aa1fbf7a74821a2d07dd3b0e4a4183a [file] [log] [blame]
Avi Drissman60039d42022-09-13 21:49:051// Copyright 2012 The Chromium Authors
[email protected]9428edc2009-11-18 18:02:472// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
noelc8702c42017-03-16 08:51:195#include "extensions/browser/sandboxed_unpacker.h"
Giovanni Ortuño Urquidi42d04f92022-07-28 07:40:396#include "build/build_config.h"
noelc8702c42017-03-16 08:51:197
Peter Boström5effa322021-04-02 22:39:398#include <memory>
Avi Drissman29071472022-01-11 19:43:519#include <tuple>
Peter Boström5effa322021-04-02 22:39:3910
asargentc4fdad22015-08-28 22:44:3911#include "base/base64.h"
[email protected]43c05d902013-07-10 21:27:0012#include "base/bind.h"
danakjdb9ae7942020-11-11 16:01:3513#include "base/callback_helpers.h"
ginkage553af3202015-02-04 12:39:0914#include "base/command_line.h"
thestig18dfb7a52014-08-26 10:44:0415#include "base/files/file_util.h"
Keishi Hattori0e45c022021-11-27 09:25:5216#include "base/memory/raw_ptr.h"
[email protected]3b63f8f42011-03-28 01:54:1517#include "base/memory/ref_counted.h"
[email protected]9428edc2009-11-18 18:02:4718#include "base/path_service.h"
[email protected]43c05d902013-07-10 21:27:0019#include "base/run_loop.h"
Jay Civelli6d0e68e2018-01-24 16:42:5320#include "base/strings/pattern.h"
[email protected]46acbf12013-06-10 18:43:4221#include "base/strings/string_util.h"
Jay Civelliea8f3df2018-01-24 05:17:3222#include "base/strings/utf_string_conversions.h"
Miyoung Shin3a9de442022-08-04 02:17:3523#include "base/threading/thread.h"
gab273138e2016-05-11 18:09:3924#include "base/threading/thread_task_runner_handle.h"
[email protected]f3a1c642011-07-12 19:15:0325#include "base/values.h"
asargentc4fdad22015-08-28 22:44:3926#include "components/crx_file/id_util.h"
Ken Rockot61df0412019-07-26 17:12:1927#include "components/services/unzip/content/unzip_service.h"
28#include "components/services/unzip/in_process_unzipper.h"
Alex Kalugina34f8c02017-07-27 11:33:0329#include "content/public/browser/browser_thread.h"
Gabriel Charettec7108742019-08-23 03:31:4030#include "content/public/test/browser_task_environment.h"
[email protected]43c05d902013-07-10 21:27:0031#include "content/public/test/test_utils.h"
asargent275faaa2015-01-27 23:43:2932#include "extensions/browser/extensions_test.h"
Minh X. Nguyen8803f4e2018-05-25 01:03:1033#include "extensions/browser/install/crx_install_error.h"
34#include "extensions/browser/install/sandboxed_unpacker_failure_reason.h"
[email protected]993da5e2013-03-23 21:25:1635#include "extensions/common/constants.h"
[email protected]e4452d32013-11-15 23:07:4136#include "extensions/common/extension.h"
asargent12a9cab72015-01-16 21:34:1637#include "extensions/common/extension_paths.h"
Oleg Davydov795d1b602020-01-02 09:44:2738#include "extensions/common/file_util.h"
Jay Civelli6d0e68e2018-01-24 16:42:5339#include "extensions/common/manifest_constants.h"
ginkage553af3202015-02-04 12:39:0940#include "extensions/common/switches.h"
Joshua Pawlicki735b92d2019-11-13 22:39:1741#include "extensions/common/value_builder.h"
Joshua Pawlickifd01b7c2019-01-17 16:18:3442#include "extensions/common/verifier_formats.h"
Jay Civelli26a85642018-01-26 21:29:3943#include "extensions/strings/grit/extensions_strings.h"
Jay Civelliea8f3df2018-01-24 05:17:3244#include "extensions/test/test_extensions_client.h"
Ken Rockotdc32df892019-11-01 06:32:1045#include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h"
Minh X. Nguyen8803f4e2018-05-25 01:03:1046#include "testing/gmock/include/gmock/gmock.h"
[email protected]9428edc2009-11-18 18:02:4747#include "testing/gtest/include/gtest/gtest.h"
48#include "third_party/skia/include/core/SkBitmap.h"
asargentc4fdad22015-08-28 22:44:3949#include "third_party/zlib/google/zip.h"
Jay Civelli26a85642018-01-26 21:29:3950#include "ui/base/l10n/l10n_util.h"
[email protected]9428edc2009-11-18 18:02:4751
[email protected]f5ac2742012-07-02 17:50:5852namespace extensions {
53
Jay Civelliea8f3df2018-01-24 05:17:3254namespace {
55
56// Inserts an illegal path into the browser images returned by
57// TestExtensionsClient for any extension.
58class IllegalImagePathInserter
59 : public TestExtensionsClient::BrowserImagePathsFilter {
60 public:
61 IllegalImagePathInserter(TestExtensionsClient* client) : client_(client) {
62 client_->AddBrowserImagePathsFilter(this);
63 }
64
65 virtual ~IllegalImagePathInserter() {
66 client_->RemoveBrowserImagePathsFilter(this);
67 }
68
69 void Filter(const Extension* extension,
70 std::set<base::FilePath>* paths) override {
71 base::FilePath illegal_path =
72 base::FilePath(base::FilePath::kParentDirectory)
73 .AppendASCII(kTempExtensionName)
74 .AppendASCII("product_logo_128.png");
75 paths->insert(illegal_path);
76 }
77
78 private:
Keishi Hattori0e45c022021-11-27 09:25:5279 raw_ptr<TestExtensionsClient> client_;
Jay Civelliea8f3df2018-01-24 05:17:3280};
81
82} // namespace
83
[email protected]f5ac2742012-07-02 17:50:5884class MockSandboxedUnpackerClient : public SandboxedUnpackerClient {
[email protected]9428edc2009-11-18 18:02:4785 public:
Miyoung Shin3a9de442022-08-04 02:17:3586 explicit MockSandboxedUnpackerClient(
87 scoped_refptr<base::SequencedTaskRunner> callback_runner)
88 : callback_runner_(callback_runner) {}
[email protected]5f2a4752012-04-27 22:18:5889
[email protected]43c05d902013-07-10 21:27:0090 base::FilePath temp_dir() const { return temp_dir_; }
Jan Wilken Dörrie85285b02021-03-11 23:38:4791 std::u16string unpack_error_message() const {
Minh X. Nguyen8803f4e2018-05-25 01:03:1092 if (error_)
93 return error_->message();
Jan Wilken Dörrie85285b02021-03-11 23:38:4794 return std::u16string();
Minh X. Nguyen8803f4e2018-05-25 01:03:1095 }
96 CrxInstallErrorType unpack_error_type() const {
97 if (error_)
98 return error_->type();
99 return CrxInstallErrorType::NONE;
100 }
101 int unpack_error_detail() const {
102 if (error_) {
103 return error_->type() == CrxInstallErrorType::SANDBOXED_UNPACKER_FAILURE
104 ? static_cast<int>(error_->sandbox_failure_detail())
105 : static_cast<int>(error_->detail());
106 }
107 return 0;
108 }
[email protected]43c05d902013-07-10 21:27:00109
Jay Civelli26a85642018-01-26 21:29:39110 void set_deleted_tracker(bool* deleted_tracker) {
111 deleted_tracker_ = deleted_tracker;
112 }
113
Oleg Davydov795d1b602020-01-02 09:44:27114 void set_should_compute_hashes(bool should_compute_hashes) {
115 should_compute_hashes_ = should_compute_hashes;
116 }
117
Miyoung Shin3a9de442022-08-04 02:17:35118 void SetQuitClosure(base::OnceClosure quit_closure) {
119 quit_closure_ = std::move(quit_closure);
120 }
121
[email protected]43c05d902013-07-10 21:27:00122 private:
Jay Civelli26a85642018-01-26 21:29:39123 ~MockSandboxedUnpackerClient() override {
124 if (deleted_tracker_)
125 *deleted_tracker_ = true;
Miyoung Shin3a9de442022-08-04 02:17:35126 if (quit_closure_)
127 std::move(quit_closure_).Run();
Jay Civelli26a85642018-01-26 21:29:39128 }
[email protected]43c05d902013-07-10 21:27:00129
Oleg Davydov795d1b602020-01-02 09:44:27130 void ShouldComputeHashesForOffWebstoreExtension(
131 scoped_refptr<const Extension> extension,
132 base::OnceCallback<void(bool)> callback) override {
133 std::move(callback).Run(should_compute_hashes_);
134 }
135
Kelvin Jiang3c2bf33c2020-08-25 00:32:30136 void OnUnpackSuccess(const base::FilePath& temp_dir,
137 const base::FilePath& extension_root,
138 std::unique_ptr<base::DictionaryValue> original_manifest,
139 const Extension* extension,
140 const SkBitmap& install_icon,
141 declarative_net_request::RulesetInstallPrefs
142 ruleset_install_prefs) override {
[email protected]43c05d902013-07-10 21:27:00143 temp_dir_ = temp_dir;
Miyoung Shin3a9de442022-08-04 02:17:35144 callback_runner_->PostTask(FROM_HERE, std::move(quit_closure_));
[email protected]43c05d902013-07-10 21:27:00145 }
146
ginkage47e603e2015-02-27 08:42:41147 void OnUnpackFailure(const CrxInstallError& error) override {
Minh X. Nguyen8803f4e2018-05-25 01:03:10148 error_ = error;
Miyoung Shin3a9de442022-08-04 02:17:35149 callback_runner_->PostTask(FROM_HERE, std::move(quit_closure_));
[email protected]43c05d902013-07-10 21:27:00150 }
151
Miyoung Shin3a9de442022-08-04 02:17:35152 scoped_refptr<base::SequencedTaskRunner> callback_runner_;
Anton Bikineev6d678472021-05-15 18:48:51153 absl::optional<CrxInstallError> error_;
danakj166a39122019-11-29 16:05:26154 base::OnceClosure quit_closure_;
[email protected]43c05d902013-07-10 21:27:00155 base::FilePath temp_dir_;
Keishi Hattori0e45c022021-11-27 09:25:52156 raw_ptr<bool> deleted_tracker_ = nullptr;
Oleg Davydov795d1b602020-01-02 09:44:27157 bool should_compute_hashes_ = false;
[email protected]9428edc2009-11-18 18:02:47158};
159
asargent275faaa2015-01-27 23:43:29160class SandboxedUnpackerTest : public ExtensionsTest {
[email protected]9428edc2009-11-18 18:02:47161 public:
danakjaee67172017-06-13 16:37:02162 SandboxedUnpackerTest()
Miyoung Shin3a9de442022-08-04 02:17:35163 : ExtensionsTest(content::BrowserTaskEnvironment::IO_MAINLOOP),
164 unpacker_thread_("Unpacker Thread") {}
Alex Kalugina34f8c02017-07-27 11:33:03165
dcheng72191812014-10-28 20:49:56166 void SetUp() override {
asargent275faaa2015-01-27 23:43:29167 ExtensionsTest::SetUp();
Miyoung Shin3a9de442022-08-04 02:17:35168
169 unpacker_thread_.Start();
170 unpacker_task_runner_ = unpacker_thread_.task_runner();
171
asargent275faaa2015-01-27 23:43:29172 ASSERT_TRUE(extensions_dir_.CreateUniqueTempDir());
Peter Boström5effa322021-04-02 22:39:39173 in_process_utility_thread_helper_ =
174 std::make_unique<content::InProcessUtilityThreadHelper>();
[email protected]9428edc2009-11-18 18:02:47175 // It will delete itself.
Miyoung Shin3a9de442022-08-04 02:17:35176 client_ = new MockSandboxedUnpackerClient(
177 task_environment()->GetMainThreadTaskRunner());
asargentc4fdad22015-08-28 22:44:39178
Ken Rockotdc32df892019-11-01 06:32:10179 InitSandboxedUnpacker();
Ken Rockot61df0412019-07-26 17:12:19180
181 // By default, we host an in-process UnzipperImpl to support any service
182 // clients. Tests may explicitly override the launch callback to prevent
183 // this.
184 unzip::SetUnzipperLaunchOverrideForTesting(
185 base::BindRepeating(&unzip::LaunchInProcessUnzipper));
Jay Civellib6f2cc9c2018-03-10 01:13:57186 }
187
Ken Rockotdc32df892019-11-01 06:32:10188 void InitSandboxedUnpacker() {
Miyoung Shin3a9de442022-08-04 02:17:35189 sandboxed_unpacker_ = new SandboxedUnpacker(
190 mojom::ManifestLocation::kInternal, Extension::NO_FLAGS,
191 extensions_dir_.GetPath(), unpacker_task_runner_, client_);
Ken Rockota373add2018-10-30 23:22:42192 }
193
dcheng72191812014-10-28 20:49:56194 void TearDown() override {
Ken Rockot61df0412019-07-26 17:12:19195 unzip::SetUnzipperLaunchOverrideForTesting(base::NullCallback());
[email protected]f5ac2742012-07-02 17:50:58196 // Need to destruct SandboxedUnpacker before the message loop since
[email protected]38f285a52010-11-05 21:02:28197 // it posts a task to it.
danakjaee67172017-06-13 16:37:02198 sandboxed_unpacker_ = nullptr;
[email protected]43c05d902013-07-10 21:27:00199 base::RunLoop().RunUntilIdle();
asargent275faaa2015-01-27 23:43:29200 ExtensionsTest::TearDown();
danakjaee67172017-06-13 16:37:02201 in_process_utility_thread_helper_.reset();
Miyoung Shin3a9de442022-08-04 02:17:35202
203 unpacker_thread_.Stop();
[email protected]9428edc2009-11-18 18:02:47204 }
205
asargentc4fdad22015-08-28 22:44:39206 base::FilePath GetCrxFullPath(const std::string& crx_name) {
207 base::FilePath full_path;
Avi Drissman210441b72018-05-01 15:51:00208 EXPECT_TRUE(base::PathService::Get(extensions::DIR_TEST_DATA, &full_path));
asargentc4fdad22015-08-28 22:44:39209 full_path = full_path.AppendASCII("unpacker").AppendASCII(crx_name);
210 EXPECT_TRUE(base::PathExists(full_path)) << full_path.value();
211 return full_path;
212 }
213
ginkage553af3202015-02-04 12:39:09214 void SetupUnpacker(const std::string& crx_name,
215 const std::string& package_hash) {
asargentc4fdad22015-08-28 22:44:39216 base::FilePath crx_path = GetCrxFullPath(crx_name);
Saurabh Nijhara156c9dd2020-04-29 20:44:19217 extensions::CRXFileInfo crx_info(crx_path, GetTestVerifierFormat());
218 crx_info.expected_hash = package_hash;
Miyoung Shin3a9de442022-08-04 02:17:35219
220 base::RunLoop run_loop;
221 client_->SetQuitClosure(run_loop.QuitClosure());
222
223 unpacker_task_runner_->PostTask(
Saurabh Nijhara156c9dd2020-04-29 20:44:19224 FROM_HERE, base::BindOnce(&SandboxedUnpacker::StartWithCrx,
225 sandboxed_unpacker_, crx_info));
Miyoung Shin3a9de442022-08-04 02:17:35226 // Wait for unpack
227 run_loop.Run();
asargentc4fdad22015-08-28 22:44:39228 }
229
230 void SetupUnpackerWithDirectory(const std::string& crx_name) {
231 base::ScopedTempDir temp_dir;
232 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
233 base::FilePath crx_path = GetCrxFullPath(crx_name);
vabr9142fe22016-09-08 13:19:22234 ASSERT_TRUE(zip::Unzip(crx_path, temp_dir.GetPath()));
asargentc4fdad22015-08-28 22:44:39235
236 std::string fake_id = crx_file::id_util::GenerateId(crx_name);
237 std::string fake_public_key;
238 base::Base64Encode(std::string(2048, 'k'), &fake_public_key);
Miyoung Shin3a9de442022-08-04 02:17:35239
240 base::RunLoop run_loop;
241 client_->SetQuitClosure(run_loop.QuitClosure());
242
243 unpacker_task_runner_->PostTask(
kylechar0686a5232019-02-19 14:10:29244 FROM_HERE, base::BindOnce(&SandboxedUnpacker::StartWithDirectory,
245 sandboxed_unpacker_, fake_id, fake_public_key,
246 temp_dir.Take()));
Miyoung Shin3a9de442022-08-04 02:17:35247
248 // Wait for unpack
249 run_loop.Run();
[email protected]9428edc2009-11-18 18:02:47250 }
251
Jay Civelliea8f3df2018-01-24 05:17:32252 bool InstallSucceeded() const { return !client_->temp_dir().empty(); }
253
254 base::FilePath GetInstallPath() const {
[email protected]b22c8af62013-07-23 23:17:02255 return client_->temp_dir().AppendASCII(kTempExtensionName);
[email protected]b0b3abd92010-04-30 17:00:09256 }
257
Jan Wilken Dörrie85285b02021-03-11 23:38:47258 std::u16string GetInstallErrorMessage() const {
Minh X. Nguyen8803f4e2018-05-25 01:03:10259 return client_->unpack_error_message();
260 }
261
262 CrxInstallErrorType GetInstallErrorType() const {
263 return client_->unpack_error_type();
264 }
265
266 int GetInstallErrorDetail() const { return client_->unpack_error_detail(); }
ginkage553af3202015-02-04 12:39:09267
Jay Civelli26a85642018-01-26 21:29:39268 void ExpectInstallErrorContains(const std::string& error) {
Minh X. Nguyen8803f4e2018-05-25 01:03:10269 std::string full_error = base::UTF16ToUTF8(client_->unpack_error_message());
Jay Civelli26a85642018-01-26 21:29:39270 EXPECT_TRUE(full_error.find(error) != std::string::npos)
271 << "Error message " << full_error << " does not contain " << error;
272 }
273
274 // Unpacks the package |package_name| and checks that |sandboxed_unpacker_|
275 // gets deleted.
276 void TestSandboxedUnpackerDeleted(const std::string& package_name,
277 bool expect_success) {
278 bool client_deleted = false;
279 client_->set_deleted_tracker(&client_deleted);
280 SetupUnpacker(package_name, "");
Minh X. Nguyen8803f4e2018-05-25 01:03:10281 EXPECT_EQ(GetInstallErrorMessage().empty(), expect_success);
Miyoung Shin3a9de442022-08-04 02:17:35282
283 base::RunLoop run_loop;
284 client_->SetQuitClosure(run_loop.QuitClosure());
285
Jay Civelli26a85642018-01-26 21:29:39286 // Remove our reference to |sandboxed_unpacker_|, it should get deleted
287 // since/ it's the last reference.
288 sandboxed_unpacker_ = nullptr;
Miyoung Shin3a9de442022-08-04 02:17:35289
290 // Wait for |client_| dtor.
291 run_loop.Run();
292
Jay Civelli26a85642018-01-26 21:29:39293 // The SandboxedUnpacker should have been deleted and deleted the client.
294 EXPECT_TRUE(client_deleted);
295 }
296
Joshua Pawlicki735b92d2019-11-13 22:39:17297 void SetPublicKey(const std::string& key) {
298 sandboxed_unpacker_->public_key_ = key;
299 }
300
301 void SetExtensionRoot(const base::FilePath& path) {
302 sandboxed_unpacker_->extension_root_ = path;
303 }
304
Anton Bikineev6d678472021-05-15 18:48:51305 absl::optional<base::Value> RewriteManifestFile(const base::Value& manifest) {
Joshua Pawlicki735b92d2019-11-13 22:39:17306 return sandboxed_unpacker_->RewriteManifestFile(manifest);
307 }
308
Ken Rockotdc32df892019-11-01 06:32:10309 data_decoder::test::InProcessDataDecoder& in_process_data_decoder() {
310 return in_process_data_decoder_;
311 }
312
[email protected]9428edc2009-11-18 18:02:47313 protected:
[email protected]ea1a3f62012-11-16 20:34:23314 base::ScopedTempDir extensions_dir_;
Keishi Hattori0e45c022021-11-27 09:25:52315 raw_ptr<MockSandboxedUnpackerClient> client_;
[email protected]f5ac2742012-07-02 17:50:58316 scoped_refptr<SandboxedUnpacker> sandboxed_unpacker_;
dchengf5d241082016-04-21 03:43:11317 std::unique_ptr<content::InProcessUtilityThreadHelper>
[email protected]c514acf2014-01-09 07:16:52318 in_process_utility_thread_helper_;
Ken Rockota373add2018-10-30 23:22:42319
Ken Rockotdc32df892019-11-01 06:32:10320 data_decoder::test::InProcessDataDecoder in_process_data_decoder_;
Miyoung Shin3a9de442022-08-04 02:17:35321
322 private:
323 // The thread where the sandboxed unpacker runs. This provides test coverage
324 // in an environment similar to what we use in production.
325 base::Thread unpacker_thread_;
326
327 scoped_refptr<base::SequencedTaskRunner> unpacker_task_runner_;
[email protected]9428edc2009-11-18 18:02:47328};
329
Jay Civelli26a85642018-01-26 21:29:39330TEST_F(SandboxedUnpackerTest, EmptyDefaultLocale) {
331 SetupUnpacker("empty_default_locale.crx", "");
332 ExpectInstallErrorContains(manifest_errors::kInvalidDefaultLocale);
Minh X. Nguyen8803f4e2018-05-25 01:03:10333 ASSERT_EQ(CrxInstallErrorType::SANDBOXED_UNPACKER_FAILURE,
334 GetInstallErrorType());
335 EXPECT_EQ(
336 static_cast<int>(SandboxedUnpackerFailureReason::UNPACKER_CLIENT_FAILED),
337 GetInstallErrorDetail());
Jay Civelli26a85642018-01-26 21:29:39338}
339
340TEST_F(SandboxedUnpackerTest, HasDefaultLocaleMissingLocalesFolder) {
341 SetupUnpacker("has_default_missing_locales.crx", "");
342 ExpectInstallErrorContains(manifest_errors::kLocalesTreeMissing);
Minh X. Nguyen8803f4e2018-05-25 01:03:10343 ASSERT_EQ(CrxInstallErrorType::SANDBOXED_UNPACKER_FAILURE,
344 GetInstallErrorType());
345 EXPECT_EQ(
346 static_cast<int>(SandboxedUnpackerFailureReason::UNPACKER_CLIENT_FAILED),
347 GetInstallErrorDetail());
Jay Civelli26a85642018-01-26 21:29:39348}
349
350TEST_F(SandboxedUnpackerTest, InvalidDefaultLocale) {
351 SetupUnpacker("invalid_default_locale.crx", "");
352 ExpectInstallErrorContains(manifest_errors::kInvalidDefaultLocale);
Minh X. Nguyen8803f4e2018-05-25 01:03:10353 ASSERT_EQ(CrxInstallErrorType::SANDBOXED_UNPACKER_FAILURE,
354 GetInstallErrorType());
355 EXPECT_EQ(
356 static_cast<int>(SandboxedUnpackerFailureReason::UNPACKER_CLIENT_FAILED),
357 GetInstallErrorDetail());
Jay Civelli26a85642018-01-26 21:29:39358}
359
360TEST_F(SandboxedUnpackerTest, MissingDefaultData) {
361 SetupUnpacker("missing_default_data.crx", "");
362 ExpectInstallErrorContains(manifest_errors::kLocalesNoDefaultMessages);
Minh X. Nguyen8803f4e2018-05-25 01:03:10363 ASSERT_EQ(CrxInstallErrorType::SANDBOXED_UNPACKER_FAILURE,
364 GetInstallErrorType());
365 EXPECT_EQ(
366 static_cast<int>(SandboxedUnpackerFailureReason::UNPACKER_CLIENT_FAILED),
367 GetInstallErrorDetail());
Jay Civelli26a85642018-01-26 21:29:39368}
369
370TEST_F(SandboxedUnpackerTest, MissingDefaultLocaleHasLocalesFolder) {
371 SetupUnpacker("missing_default_has_locales.crx", "");
372 ExpectInstallErrorContains(l10n_util::GetStringUTF8(
373 IDS_EXTENSION_LOCALES_NO_DEFAULT_LOCALE_SPECIFIED));
Minh X. Nguyen8803f4e2018-05-25 01:03:10374 ASSERT_EQ(CrxInstallErrorType::SANDBOXED_UNPACKER_FAILURE,
375 GetInstallErrorType());
376 EXPECT_EQ(
377 static_cast<int>(SandboxedUnpackerFailureReason::UNPACKER_CLIENT_FAILED),
378 GetInstallErrorDetail());
Jay Civelli26a85642018-01-26 21:29:39379}
380
381TEST_F(SandboxedUnpackerTest, MissingMessagesFile) {
382 SetupUnpacker("missing_messages_file.crx", "");
383 EXPECT_TRUE(base::MatchPattern(
Minh X. Nguyen8803f4e2018-05-25 01:03:10384 GetInstallErrorMessage(),
Peter Varga3b99c262021-12-01 22:24:06385 u"*" + std::u16string(manifest_errors::kLocalesMessagesFileMissing) +
Jan Wilken Dörriec92a6d7242021-03-23 17:43:48386 u"*_locales?en_US?messages.json'."))
Minh X. Nguyen8803f4e2018-05-25 01:03:10387 << GetInstallErrorMessage();
388 ASSERT_EQ(CrxInstallErrorType::SANDBOXED_UNPACKER_FAILURE,
389 GetInstallErrorType());
390 EXPECT_EQ(
391 static_cast<int>(SandboxedUnpackerFailureReason::UNPACKER_CLIENT_FAILED),
392 GetInstallErrorDetail());
Jay Civelli26a85642018-01-26 21:29:39393}
394
395TEST_F(SandboxedUnpackerTest, NoLocaleData) {
396 SetupUnpacker("no_locale_data.crx", "");
397 ExpectInstallErrorContains(manifest_errors::kLocalesNoDefaultMessages);
Minh X. Nguyen8803f4e2018-05-25 01:03:10398 ASSERT_EQ(CrxInstallErrorType::SANDBOXED_UNPACKER_FAILURE,
399 GetInstallErrorType());
400 EXPECT_EQ(
401 static_cast<int>(SandboxedUnpackerFailureReason::UNPACKER_CLIENT_FAILED),
402 GetInstallErrorDetail());
Jay Civelli26a85642018-01-26 21:29:39403}
404
Jay Civelliea8f3df2018-01-24 05:17:32405TEST_F(SandboxedUnpackerTest, ImageDecodingError) {
Peter Kastingaae6db932021-05-04 12:02:11406 const char16_t kExpected[] = u"Could not decode image: ";
Jay Civelliea8f3df2018-01-24 05:17:32407 SetupUnpacker("bad_image.crx", "");
Peter Kastingaae6db932021-05-04 12:02:11408 EXPECT_TRUE(base::StartsWith(GetInstallErrorMessage(), kExpected,
Jay Civelliea8f3df2018-01-24 05:17:32409 base::CompareCase::INSENSITIVE_ASCII))
410 << "Expected prefix: \"" << kExpected << "\", actual error: \""
Minh X. Nguyen8803f4e2018-05-25 01:03:10411 << GetInstallErrorMessage() << "\"";
412 ASSERT_EQ(CrxInstallErrorType::SANDBOXED_UNPACKER_FAILURE,
413 GetInstallErrorType());
414 EXPECT_EQ(
415 static_cast<int>(SandboxedUnpackerFailureReason::UNPACKER_CLIENT_FAILED),
416 GetInstallErrorDetail());
Jay Civelliea8f3df2018-01-24 05:17:32417}
418
419TEST_F(SandboxedUnpackerTest, BadPathError) {
420 IllegalImagePathInserter inserter(
421 static_cast<TestExtensionsClient*>(ExtensionsClient::Get()));
422 SetupUnpacker("good_package.crx", "");
423 // Install should have failed with an error.
424 EXPECT_FALSE(InstallSucceeded());
Minh X. Nguyen8803f4e2018-05-25 01:03:10425 EXPECT_FALSE(GetInstallErrorMessage().empty());
426 ASSERT_EQ(CrxInstallErrorType::SANDBOXED_UNPACKER_FAILURE,
427 GetInstallErrorType());
428 EXPECT_EQ(static_cast<int>(
429 SandboxedUnpackerFailureReason::INVALID_PATH_FOR_BROWSER_IMAGE),
430 GetInstallErrorDetail());
Jay Civelliea8f3df2018-01-24 05:17:32431}
432
[email protected]f5ac2742012-07-02 17:50:58433TEST_F(SandboxedUnpackerTest, NoCatalogsSuccess) {
ginkage553af3202015-02-04 12:39:09434 SetupUnpacker("no_l10n.crx", "");
[email protected]9428edc2009-11-18 18:02:47435 // Check that there is no _locales folder.
asargent275faaa2015-01-27 23:43:29436 base::FilePath install_path = GetInstallPath().Append(kLocaleFolder);
[email protected]7567484142013-07-11 17:36:07437 EXPECT_FALSE(base::PathExists(install_path));
Minh X. Nguyen8803f4e2018-05-25 01:03:10438 EXPECT_EQ(CrxInstallErrorType::NONE, GetInstallErrorType());
[email protected]9428edc2009-11-18 18:02:47439}
440
asargentc4fdad22015-08-28 22:44:39441TEST_F(SandboxedUnpackerTest, FromDirNoCatalogsSuccess) {
442 SetupUnpackerWithDirectory("no_l10n.crx");
443 // Check that there is no _locales folder.
444 base::FilePath install_path = GetInstallPath().Append(kLocaleFolder);
445 EXPECT_FALSE(base::PathExists(install_path));
Minh X. Nguyen8803f4e2018-05-25 01:03:10446 EXPECT_EQ(CrxInstallErrorType::NONE, GetInstallErrorType());
asargentc4fdad22015-08-28 22:44:39447}
448
[email protected]11170a772013-12-13 11:38:32449TEST_F(SandboxedUnpackerTest, WithCatalogsSuccess) {
ginkage553af3202015-02-04 12:39:09450 SetupUnpacker("good_l10n.crx", "");
[email protected]43c05d902013-07-10 21:27:00451 // Check that there is _locales folder.
asargent275faaa2015-01-27 23:43:29452 base::FilePath install_path = GetInstallPath().Append(kLocaleFolder);
[email protected]7567484142013-07-11 17:36:07453 EXPECT_TRUE(base::PathExists(install_path));
Minh X. Nguyen8803f4e2018-05-25 01:03:10454 EXPECT_EQ(CrxInstallErrorType::NONE, GetInstallErrorType());
[email protected]9428edc2009-11-18 18:02:47455}
[email protected]f5ac2742012-07-02 17:50:58456
asargentc4fdad22015-08-28 22:44:39457TEST_F(SandboxedUnpackerTest, FromDirWithCatalogsSuccess) {
458 SetupUnpackerWithDirectory("good_l10n.crx");
459 // Check that there is _locales folder.
460 base::FilePath install_path = GetInstallPath().Append(kLocaleFolder);
461 EXPECT_TRUE(base::PathExists(install_path));
Minh X. Nguyen8803f4e2018-05-25 01:03:10462 EXPECT_EQ(CrxInstallErrorType::NONE, GetInstallErrorType());
asargentc4fdad22015-08-28 22:44:39463}
464
Miyoung Shin3a9de442022-08-04 02:17:35465TEST_F(SandboxedUnpackerTest, FailHashCheck) {
ginkage553af3202015-02-04 12:39:09466 base::CommandLine::ForCurrentProcess()->AppendSwitch(
467 extensions::switches::kEnableCrxHashCheck);
waffles5918d5f2017-05-23 01:45:28468 SetupUnpacker("good_l10n.crx", std::string(64, '0'));
ginkage553af3202015-02-04 12:39:09469 // Check that there is an error message.
Minh X. Nguyen8803f4e2018-05-25 01:03:10470 EXPECT_FALSE(GetInstallErrorMessage().empty());
471 ASSERT_EQ(CrxInstallErrorType::SANDBOXED_UNPACKER_FAILURE,
472 GetInstallErrorType());
473 EXPECT_EQ(static_cast<int>(
474 SandboxedUnpackerFailureReason::CRX_HASH_VERIFICATION_FAILED),
475 GetInstallErrorDetail());
ginkage553af3202015-02-04 12:39:09476}
477
Joshua Pawlicki735b92d2019-11-13 22:39:17478TEST_F(SandboxedUnpackerTest, TestRewriteManifestInjections) {
479 constexpr char kTestKey[] = "test_key";
480 constexpr char kTestVersion[] = "1.2.3";
481 constexpr char kVersionStr[] = "version";
482 SetPublicKey(kTestKey);
483 SetExtensionRoot(extensions_dir_.GetPath());
484 std::string fingerprint = "1.0123456789abcdef";
485 base::WriteFile(extensions_dir_.GetPath().Append(
486 FILE_PATH_LITERAL("manifest.fingerprint")),
487 fingerprint.c_str(),
488 base::checked_cast<int>(fingerprint.size()));
Anton Bikineev6d678472021-05-15 18:48:51489 absl::optional<base::Value> manifest(RewriteManifestFile(
Joshua Pawlicki735b92d2019-11-13 22:39:17490 *DictionaryBuilder().Set(kVersionStr, kTestVersion).Build()));
491 auto* key = manifest->FindStringKey("key");
492 auto* version = manifest->FindStringKey(kVersionStr);
493 auto* differential_fingerprint =
494 manifest->FindStringKey("differential_fingerprint");
495 ASSERT_NE(nullptr, key);
496 ASSERT_NE(nullptr, version);
497 ASSERT_NE(nullptr, differential_fingerprint);
498 EXPECT_EQ(kTestKey, *key);
499 EXPECT_EQ(kTestVersion, *version);
500 EXPECT_EQ(fingerprint, *differential_fingerprint);
501}
502
Jay Civelli6d0e68e2018-01-24 16:42:53503TEST_F(SandboxedUnpackerTest, InvalidMessagesFile) {
504 SetupUnpackerWithDirectory("invalid_messages_file.crx");
505 // Check that there is no _locales folder.
506 base::FilePath install_path = GetInstallPath().Append(kLocaleFolder);
507 EXPECT_FALSE(base::PathExists(install_path));
508 EXPECT_TRUE(base::MatchPattern(
Minh X. Nguyen8803f4e2018-05-25 01:03:10509 GetInstallErrorMessage(),
Jan Wilken Dörrie782626b2021-04-14 18:22:14510 u"*_locales?en_US?messages.json': Line: 4, column: 1,*"))
Minh X. Nguyen8803f4e2018-05-25 01:03:10511 << GetInstallErrorMessage();
512 ASSERT_EQ(CrxInstallErrorType::SANDBOXED_UNPACKER_FAILURE,
513 GetInstallErrorType());
514 EXPECT_EQ(static_cast<int>(
515 SandboxedUnpackerFailureReason::COULD_NOT_LOCALIZE_EXTENSION),
516 GetInstallErrorDetail());
Jay Civelli6d0e68e2018-01-24 16:42:53517}
518
ginkage553af3202015-02-04 12:39:09519TEST_F(SandboxedUnpackerTest, PassHashCheck) {
520 base::CommandLine::ForCurrentProcess()->AppendSwitch(
521 extensions::switches::kEnableCrxHashCheck);
522 SetupUnpacker(
523 "good_l10n.crx",
Devlin Cronin1de938972018-04-24 19:17:15524 "614AE3D608F4C2185E9173293AB3F93EE7C7C79C9A2C3CF71F633386A3296A6C");
ginkage553af3202015-02-04 12:39:09525 // Check that there is no error message.
Minh X. Nguyen8803f4e2018-05-25 01:03:10526 EXPECT_THAT(GetInstallErrorMessage(), testing::IsEmpty());
527 EXPECT_EQ(CrxInstallErrorType::NONE, GetInstallErrorType());
ginkage553af3202015-02-04 12:39:09528}
529
530TEST_F(SandboxedUnpackerTest, SkipHashCheck) {
531 SetupUnpacker("good_l10n.crx", "badhash");
532 // Check that there is no error message.
Minh X. Nguyen8803f4e2018-05-25 01:03:10533 EXPECT_THAT(GetInstallErrorMessage(), testing::IsEmpty());
534 EXPECT_EQ(CrxInstallErrorType::NONE, GetInstallErrorType());
ginkage553af3202015-02-04 12:39:09535}
536
Jay Civellib6f2cc9c2018-03-10 01:13:57537// The following tests simulate the utility services failling.
538TEST_F(SandboxedUnpackerTest, UnzipperServiceFails) {
Ken Rockot61df0412019-07-26 17:12:19539 // We override the Unzipper's launching behavior to drop the interface
540 // receiver, effectively simulating a crashy service process.
541 unzip::SetUnzipperLaunchOverrideForTesting(base::BindRepeating([]() -> auto {
542 mojo::PendingRemote<unzip::mojom::Unzipper> remote;
Avi Drissman29071472022-01-11 19:43:51543 std::ignore = remote.InitWithNewPipeAndPassReceiver();
Ken Rockot61df0412019-07-26 17:12:19544 return remote;
545 }));
546
Ken Rockotdc32df892019-11-01 06:32:10547 InitSandboxedUnpacker();
Jay Civellib6f2cc9c2018-03-10 01:13:57548 SetupUnpacker("good_package.crx", "");
549 EXPECT_FALSE(InstallSucceeded());
Minh X. Nguyen8803f4e2018-05-25 01:03:10550 EXPECT_FALSE(GetInstallErrorMessage().empty());
551 ASSERT_EQ(CrxInstallErrorType::SANDBOXED_UNPACKER_FAILURE,
552 GetInstallErrorType());
553 EXPECT_EQ(static_cast<int>(SandboxedUnpackerFailureReason::UNZIP_FAILED),
554 GetInstallErrorDetail());
Jay Civellib6f2cc9c2018-03-10 01:13:57555}
556
557TEST_F(SandboxedUnpackerTest, JsonParserFails) {
Ken Rockotdc32df892019-11-01 06:32:10558 in_process_data_decoder().service().SimulateJsonParserCrashForTesting(true);
559 InitSandboxedUnpacker();
560
Jay Civellib6f2cc9c2018-03-10 01:13:57561 SetupUnpacker("good_package.crx", "");
562 EXPECT_FALSE(InstallSucceeded());
Minh X. Nguyen8803f4e2018-05-25 01:03:10563 EXPECT_FALSE(GetInstallErrorMessage().empty());
564 ASSERT_EQ(CrxInstallErrorType::SANDBOXED_UNPACKER_FAILURE,
565 GetInstallErrorType());
Jay Civellib6f2cc9c2018-03-10 01:13:57566}
567
568TEST_F(SandboxedUnpackerTest, ImageDecoderFails) {
Ken Rockotdc32df892019-11-01 06:32:10569 in_process_data_decoder().service().SimulateImageDecoderCrashForTesting(true);
570 InitSandboxedUnpacker();
Jay Civellib6f2cc9c2018-03-10 01:13:57571 SetupUnpacker("good_package.crx", "");
572 EXPECT_FALSE(InstallSucceeded());
Minh X. Nguyen8803f4e2018-05-25 01:03:10573 EXPECT_FALSE(GetInstallErrorMessage().empty());
574 ASSERT_EQ(CrxInstallErrorType::SANDBOXED_UNPACKER_FAILURE,
575 GetInstallErrorType());
576 EXPECT_EQ(
Lukasz Anforowicz4136a0492021-10-20 00:56:21577 static_cast<int>(SandboxedUnpackerFailureReason::UNPACKER_CLIENT_FAILED),
Minh X. Nguyen8803f4e2018-05-25 01:03:10578 GetInstallErrorDetail());
Jay Civellib6f2cc9c2018-03-10 01:13:57579}
580
Oleg Davydov795d1b602020-01-02 09:44:27581TEST_F(SandboxedUnpackerTest, NoComputeHashes) {
582 client_->set_should_compute_hashes(false);
583 SetupUnpacker("good_package.crx", "");
584 EXPECT_TRUE(InstallSucceeded());
585 EXPECT_TRUE(GetInstallErrorMessage().empty());
586 EXPECT_FALSE(
587 base::PathExists(file_util::GetComputedHashesPath(GetInstallPath())));
588}
589
590TEST_F(SandboxedUnpackerTest, ComputeHashes) {
591 client_->set_should_compute_hashes(true);
592 SetupUnpacker("good_package.crx", "");
593 EXPECT_TRUE(InstallSucceeded());
594 EXPECT_TRUE(GetInstallErrorMessage().empty());
595 EXPECT_TRUE(
596 base::PathExists(file_util::GetComputedHashesPath(GetInstallPath())));
597}
598
Jay Civelli26a85642018-01-26 21:29:39599// SandboxedUnpacker is ref counted and is reference by callbacks and
600// InterfacePtrs. This tests that it gets deleted as expected (so that no extra
601// refs are left).
602TEST_F(SandboxedUnpackerTest, DeletedOnSuccess) {
603 TestSandboxedUnpackerDeleted("good_l10n.crx", /*expect_success=*/true);
604}
605
606TEST_F(SandboxedUnpackerTest, DeletedOnFailure) {
607 TestSandboxedUnpackerDeleted("bad_image.crx", /*expect_success=*/false);
608}
609
[email protected]f5ac2742012-07-02 17:50:58610} // namespace extensions