OLD | NEW |
---|---|
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <fstream> | |
6 | |
5 #include "base/file_util.h" | 7 #include "base/file_util.h" |
6 #include "base/path_service.h" | 8 #include "base/path_service.h" |
7 #include "base/ref_counted.h" | 9 #include "base/ref_counted.h" |
8 #include "base/scoped_temp_dir.h" | 10 #include "base/scoped_temp_dir.h" |
9 #include "base/string_util.h" | 11 #include "base/string_util.h" |
12 #include "base/utf_string_conversions.h" | |
10 #include "chrome/browser/extensions/sandboxed_extension_unpacker.h" | 13 #include "chrome/browser/extensions/sandboxed_extension_unpacker.h" |
11 #include "chrome/common/chrome_paths.h" | 14 #include "chrome/common/chrome_paths.h" |
12 #include "chrome/common/extensions/extension.h" | 15 #include "chrome/common/extensions/extension.h" |
13 #include "chrome/common/extensions/extension_constants.h" | 16 #include "chrome/common/extensions/extension_constants.h" |
14 #include "chrome/common/extensions/extension_unpacker.h" | 17 #include "chrome/common/extensions/extension_unpacker.h" |
15 #include "testing/gmock/include/gmock/gmock.h" | 18 #include "testing/gmock/include/gmock/gmock.h" |
16 #include "testing/gtest/include/gtest/gtest.h" | 19 #include "testing/gtest/include/gtest/gtest.h" |
17 #include "third_party/skia/include/core/SkBitmap.h" | 20 #include "third_party/skia/include/core/SkBitmap.h" |
18 | 21 |
19 namespace errors = extension_manifest_errors; | 22 namespace errors = extension_manifest_errors; |
20 namespace keys = extension_manifest_keys; | 23 namespace keys = extension_manifest_keys; |
21 | 24 |
22 using testing::_; | 25 using testing::_; |
23 using testing::Invoke; | 26 using testing::Invoke; |
24 | 27 |
28 namespace { | |
29 | |
30 // Create a non-empty file. | |
31 void CreateTextFile(const FilePath& filename) { | |
32 std::ofstream file; | |
33 file.open(WideToUTF8(filename.ToWStringHack()).c_str()); | |
Erik does not do reviews
2011/01/14 22:34:44
This looks problematic - potential filename incomp
Sam Kerner (Chrome)
2011/01/18 19:26:45
Done.
| |
34 ASSERT_TRUE(file.is_open()); | |
35 file << "I am a text file."; | |
36 file.close(); | |
37 } | |
38 | |
39 // Clear a scoped_temp_dir if it has any contents. | |
40 void ClearScopedTempDir(ScopedTempDir& scoped_temp_dir) { | |
41 if (scoped_temp_dir.IsValid()) { | |
Erik does not do reviews
2011/01/14 22:34:44
nit: remove {}
Sam Kerner (Chrome)
2011/01/18 19:26:45
Done.
| |
42 EXPECT_TRUE(scoped_temp_dir.Delete()); | |
43 } | |
44 } | |
45 | |
25 void OnUnpackSuccess(const FilePath& temp_dir, | 46 void OnUnpackSuccess(const FilePath& temp_dir, |
26 const FilePath& extension_root, | 47 const FilePath& extension_root, |
27 const Extension* extension) { | 48 const Extension* extension) { |
28 // Don't delete temp_dir here, we need to do some post op checking. | 49 // Don't delete temp_dir here, we need to do some post op checking. |
29 } | 50 } |
30 | 51 |
52 } | |
53 | |
31 class MockSandboxedExtensionUnpackerClient | 54 class MockSandboxedExtensionUnpackerClient |
32 : public SandboxedExtensionUnpackerClient { | 55 : public SandboxedExtensionUnpackerClient { |
33 public: | 56 public: |
34 virtual ~MockSandboxedExtensionUnpackerClient() {} | 57 virtual ~MockSandboxedExtensionUnpackerClient() {} |
35 | 58 |
36 MOCK_METHOD3(OnUnpackSuccess, | 59 MOCK_METHOD3(OnUnpackSuccess, |
37 void(const FilePath& temp_dir, | 60 void(const FilePath& temp_dir, |
38 const FilePath& extension_root, | 61 const FilePath& extension_root, |
39 const Extension* extension)); | 62 const Extension* extension)); |
40 | 63 |
(...skipping 30 matching lines...) Expand all Loading... | |
71 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &original_path)); | 94 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &original_path)); |
72 original_path = original_path.AppendASCII("extensions") | 95 original_path = original_path.AppendASCII("extensions") |
73 .AppendASCII("unpacker") | 96 .AppendASCII("unpacker") |
74 .AppendASCII(crx_name); | 97 .AppendASCII(crx_name); |
75 ASSERT_TRUE(file_util::PathExists(original_path)) << original_path.value(); | 98 ASSERT_TRUE(file_util::PathExists(original_path)) << original_path.value(); |
76 | 99 |
77 // Try bots won't let us write into DIR_TEST_DATA, so we have to create | 100 // Try bots won't let us write into DIR_TEST_DATA, so we have to create |
78 // a temp folder to play in. | 101 // a temp folder to play in. |
79 ASSERT_TRUE(PathService::Get(base::DIR_TEMP, &install_dir_)); | 102 ASSERT_TRUE(PathService::Get(base::DIR_TEMP, &install_dir_)); |
80 install_dir_ = | 103 install_dir_ = |
81 install_dir_.AppendASCII("sandboxed_extension_unpacker_test"); | 104 install_dir_.AppendASCII("sandboxed_extension_unpacker_test"); |
82 file_util::Delete(install_dir_, true); | 105 file_util::Delete(install_dir_, true); |
83 file_util::CreateDirectory(install_dir_); | 106 file_util::CreateDirectory(install_dir_); |
84 | 107 |
85 FilePath crx_path = install_dir_.AppendASCII(crx_name); | 108 FilePath crx_path = install_dir_.AppendASCII(crx_name); |
86 ASSERT_TRUE(file_util::CopyFile(original_path, crx_path)) << | 109 ASSERT_TRUE(file_util::CopyFile(original_path, crx_path)) << |
87 "Original path: " << original_path.value() << | 110 "Original path: " << original_path.value() << |
88 ", Crx path: " << crx_path.value(); | 111 ", Crx path: " << crx_path.value(); |
89 | 112 |
90 unpacker_.reset(new ExtensionUnpacker(crx_path)); | 113 unpacker_.reset(new ExtensionUnpacker(crx_path)); |
91 | 114 |
92 | |
93 // Build a temp area where the extension will be unpacked. | 115 // Build a temp area where the extension will be unpacked. |
94 ASSERT_TRUE(PathService::Get(base::DIR_TEMP, &temp_dir_)); | 116 ASSERT_TRUE(PathService::Get(base::DIR_TEMP, &temp_dir_)); |
95 temp_dir_ = temp_dir_.AppendASCII("sandboxed_extension_unpacker_test_Temp"); | 117 temp_dir_ = temp_dir_.AppendASCII("sandboxed_extension_unpacker_test_Temp"); |
96 file_util::CreateDirectory(temp_dir_); | 118 ASSERT_TRUE(file_util::CreateDirectory(temp_dir_)); |
119 | |
120 //PathService::Override(chrome::DIR_USER_DATA_TEMP, temp_dir_); | |
Erik does not do reviews
2011/01/14 22:34:44
remove unused code
Sam Kerner (Chrome)
2011/01/18 19:26:45
Done.
| |
97 | 121 |
98 sandboxed_unpacker_ = | 122 sandboxed_unpacker_ = |
99 new SandboxedExtensionUnpacker(crx_path, temp_dir_, NULL, client_); | 123 new SandboxedExtensionUnpacker(crx_path, NULL, client_); |
124 | |
100 // Hack since SandboxedExtensionUnpacker gets its background thread id from | 125 // Hack since SandboxedExtensionUnpacker gets its background thread id from |
101 // the Start call, but we don't call it here. | 126 // the Start call, but we don't call it here. |
102 sandboxed_unpacker_->thread_identifier_ = BrowserThread::FILE; | 127 sandboxed_unpacker_->thread_identifier_ = BrowserThread::FILE; |
103 EXPECT_TRUE(PrepareUnpackerEnv()); | |
104 } | 128 } |
105 | 129 |
106 bool PrepareUnpackerEnv() { | 130 bool PrepareUnpackerEnv() { |
107 sandboxed_unpacker_->extension_root_ = | 131 sandboxed_unpacker_->extension_root_ = |
108 install_dir_.AppendASCII(extension_filenames::kTempExtensionName); | 132 install_dir_.AppendASCII(extension_filenames::kTempExtensionName); |
109 | 133 |
110 if (!sandboxed_unpacker_->temp_dir_.Set(install_dir_)) | 134 if (!sandboxed_unpacker_->temp_dir_.Set(install_dir_)) |
111 return false; | 135 return false; |
112 sandboxed_unpacker_->public_key_ = | 136 sandboxed_unpacker_->public_key_ = |
113 "ocnapchkplbmjmpfehjocmjnipfmogkh"; | 137 "ocnapchkplbmjmpfehjocmjnipfmogkh"; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
152 FilePath temp_dir_; | 176 FilePath temp_dir_; |
153 MockSandboxedExtensionUnpackerClient* client_; | 177 MockSandboxedExtensionUnpackerClient* client_; |
154 scoped_ptr<ExtensionUnpacker> unpacker_; | 178 scoped_ptr<ExtensionUnpacker> unpacker_; |
155 scoped_refptr<SandboxedExtensionUnpacker> sandboxed_unpacker_; | 179 scoped_refptr<SandboxedExtensionUnpacker> sandboxed_unpacker_; |
156 MessageLoop loop_; | 180 MessageLoop loop_; |
157 scoped_ptr<BrowserThread> file_thread_; | 181 scoped_ptr<BrowserThread> file_thread_; |
158 }; | 182 }; |
159 | 183 |
160 TEST_F(SandboxedExtensionUnpackerTest, NoCatalogsSuccess) { | 184 TEST_F(SandboxedExtensionUnpackerTest, NoCatalogsSuccess) { |
161 EXPECT_CALL(*client_, OnUnpackSuccess(_, _, _)); | 185 EXPECT_CALL(*client_, OnUnpackSuccess(_, _, _)); |
186 EXPECT_CALL(*client_, OnUnpackFailure(_)).Times(0); | |
162 | 187 |
163 SetupUnpacker("no_l10n.crx"); | 188 SetupUnpacker("no_l10n.crx"); |
189 PrepareUnpackerEnv(); | |
Erik does not do reviews
2011/01/14 22:34:44
shouldn't this have EXPECT or ASSERT on it? (and o
Sam Kerner (Chrome)
2011/01/18 19:26:45
Yes. Done.
| |
164 ASSERT_TRUE(unpacker_->Run()); | 190 ASSERT_TRUE(unpacker_->Run()); |
165 ASSERT_TRUE(unpacker_->DumpImagesToFile()); | 191 ASSERT_TRUE(unpacker_->DumpImagesToFile()); |
166 ASSERT_TRUE(unpacker_->DumpMessageCatalogsToFile()); | 192 ASSERT_TRUE(unpacker_->DumpMessageCatalogsToFile()); |
167 | |
168 // Check that there is no _locales folder. | 193 // Check that there is no _locales folder. |
169 FilePath install_path = | 194 FilePath install_path = |
170 GetInstallPath().Append(Extension::kLocaleFolder); | 195 GetInstallPath().Append(Extension::kLocaleFolder); |
171 EXPECT_FALSE(file_util::PathExists(install_path)); | 196 EXPECT_FALSE(file_util::PathExists(install_path)); |
172 | |
173 OnUnpackSucceeded(); | 197 OnUnpackSucceeded(); |
174 | 198 |
175 // Check that there still is no _locales folder. | 199 // Check that there still is no _locales folder. |
176 EXPECT_FALSE(file_util::PathExists(install_path)); | 200 EXPECT_FALSE(file_util::PathExists(install_path)); |
177 | 201 |
178 ASSERT_TRUE(TempFilesRemoved()); | 202 ASSERT_TRUE(TempFilesRemoved()); |
179 } | 203 } |
180 | 204 |
181 TEST_F(SandboxedExtensionUnpackerTest, WithCatalogsSuccess) { | 205 TEST_F(SandboxedExtensionUnpackerTest, WithCatalogsSuccess) { |
182 EXPECT_CALL(*client_, OnUnpackSuccess(_, _, _)); | 206 EXPECT_CALL(*client_, OnUnpackSuccess(_, _, _)); |
207 EXPECT_CALL(*client_, OnUnpackFailure(_)).Times(0); | |
183 | 208 |
184 SetupUnpacker("good_l10n.crx"); | 209 SetupUnpacker("good_l10n.crx"); |
210 PrepareUnpackerEnv(); | |
185 ASSERT_TRUE(unpacker_->Run()); | 211 ASSERT_TRUE(unpacker_->Run()); |
186 ASSERT_TRUE(unpacker_->DumpImagesToFile()); | 212 ASSERT_TRUE(unpacker_->DumpImagesToFile()); |
187 ASSERT_TRUE(unpacker_->DumpMessageCatalogsToFile()); | 213 ASSERT_TRUE(unpacker_->DumpMessageCatalogsToFile()); |
188 | 214 |
189 // Set timestamp on _locales/en_US/messages.json into the past. | 215 // Set timestamp on _locales/en_US/messages.json into the past. |
190 FilePath messages_file; | 216 FilePath messages_file; |
191 messages_file = GetInstallPath().Append(Extension::kLocaleFolder) | 217 messages_file = GetInstallPath().Append(Extension::kLocaleFolder) |
192 .AppendASCII("en_US") | 218 .AppendASCII("en_US") |
193 .Append(Extension::kMessagesFilename); | 219 .Append(Extension::kMessagesFilename); |
194 base::PlatformFileInfo old_info; | 220 base::PlatformFileInfo old_info; |
195 EXPECT_TRUE(file_util::GetFileInfo(messages_file, &old_info)); | 221 EXPECT_TRUE(file_util::GetFileInfo(messages_file, &old_info)); |
196 base::Time old_time = | 222 base::Time old_time = |
197 old_info.last_modified - base::TimeDelta::FromSeconds(2); | 223 old_info.last_modified - base::TimeDelta::FromSeconds(2); |
198 EXPECT_TRUE(file_util::SetLastModifiedTime(messages_file, old_time)); | 224 EXPECT_TRUE(file_util::SetLastModifiedTime(messages_file, old_time)); |
199 // Refresh old_info, just to be sure. | 225 // Refresh old_info, just to be sure. |
200 EXPECT_TRUE(file_util::GetFileInfo(messages_file, &old_info)); | 226 EXPECT_TRUE(file_util::GetFileInfo(messages_file, &old_info)); |
201 | 227 |
202 OnUnpackSucceeded(); | 228 OnUnpackSucceeded(); |
203 | 229 |
204 // Check that there is newer _locales/en_US/messages.json file. | 230 // Check that there is newer _locales/en_US/messages.json file. |
205 base::PlatformFileInfo new_info; | 231 base::PlatformFileInfo new_info; |
206 EXPECT_TRUE(file_util::GetFileInfo(messages_file, &new_info)); | 232 EXPECT_TRUE(file_util::GetFileInfo(messages_file, &new_info)); |
207 | 233 |
208 EXPECT_TRUE(new_info.last_modified > old_info.last_modified); | 234 EXPECT_TRUE(new_info.last_modified > old_info.last_modified); |
209 | 235 |
210 ASSERT_TRUE(TempFilesRemoved()); | 236 ASSERT_TRUE(TempFilesRemoved()); |
211 } | 237 } |
238 | |
239 TEST_F(SandboxedExtensionUnpackerTest, CreateTempDirectory) { | |
Erik does not do reviews
2011/01/14 22:34:44
If we ditch the multiple dir support for now, is t
Sam Kerner (Chrome)
2011/01/18 19:26:45
No, but it could be used to test error handling of
| |
240 // To be sure overriding path keys does not change the paths seen | |
241 // by existing code, use some path keys that do not exist outside | |
242 // this test. | |
243 enum { | |
244 PATH_START = chrome::PATH_END+1, | |
245 TEST_DIR_WORKS, | |
246 TEST_DIR_CANT_GET, | |
247 TEST_DIR_CANT_WRITE, | |
248 PATH_END | |
249 }; | |
250 | |
251 // Create a fake temp path. | |
252 ScopedTempDir fake_user_temp_dir; | |
253 ASSERT_TRUE(fake_user_temp_dir.CreateUniqueTempDir()); | |
254 | |
255 // |dir_works| will work for unpacking. | |
256 FilePath dir_works(fake_user_temp_dir.path()); | |
257 | |
258 // Needed because path service code runs AbsolutePath() on all values | |
259 // it returns. This changes the path on the mac trybots, and we need | |
260 // to compare this path to the result from PathService::Get() below. | |
261 ASSERT_TRUE(file_util::AbsolutePath(&dir_works)); | |
262 | |
263 // To make directory creation fail, use a base path which is a file. | |
264 FilePath dir_cant_write(fake_user_temp_dir.path().AppendASCII("cant_write")); | |
265 CreateTextFile(dir_cant_write); | |
266 | |
267 // Set up test paths: | |
268 PathService::Override(TEST_DIR_WORKS, dir_works); | |
269 PathService::Override(TEST_DIR_CANT_GET, FilePath()); | |
270 PathService::Override(TEST_DIR_CANT_WRITE, dir_cant_write); | |
271 | |
272 // Test that our path keys give paths with the desired properties: | |
273 FilePath scratch; | |
274 ASSERT_TRUE(PathService::Get(TEST_DIR_WORKS, &scratch)); | |
275 ASSERT_EQ(dir_works.value(), scratch.value()); | |
276 | |
277 ASSERT_FALSE(PathService::Get(TEST_DIR_CANT_GET, &scratch)); | |
278 | |
279 ASSERT_TRUE(PathService::Get(TEST_DIR_CANT_WRITE, &scratch)); | |
280 ASSERT_EQ(dir_cant_write.value(), scratch.value()); | |
281 ASSERT_FALSE(file_util::CreateDirectory( | |
282 dir_cant_write.AppendASCII("cant_make_dir_in_a_file"))); | |
283 | |
284 SetupUnpacker("good_l10n.crx"); | |
285 | |
286 // Test that a valid, writable path is read and used. | |
287 const int kWorkingDir[] = { | |
288 TEST_DIR_WORKS | |
289 }; | |
290 // Clear |temp_dir_|, so that we can test that it was set. | |
291 ClearScopedTempDir(sandboxed_unpacker_->temp_dir_); | |
292 EXPECT_CALL(*client_, OnUnpackFailure(_)).Times(0); | |
293 ASSERT_TRUE(sandboxed_unpacker_->CreateTempDirectory( | |
294 kWorkingDir, arraysize(kWorkingDir))); | |
295 ASSERT_EQ(dir_works.value(), | |
296 sandboxed_unpacker_->temp_dir_.path().DirName().value()); | |
297 | |
298 // Test that two unusable paths both fail. | |
299 const int kFailingDir[] = { | |
300 TEST_DIR_CANT_GET, | |
301 TEST_DIR_CANT_WRITE | |
302 }; | |
303 ClearScopedTempDir(sandboxed_unpacker_->temp_dir_); | |
304 EXPECT_CALL(*client_, OnUnpackFailure(_)).Times(1); | |
305 ASSERT_FALSE(sandboxed_unpacker_->CreateTempDirectory( | |
306 kFailingDir, arraysize(kFailingDir))); | |
307 | |
308 // If at first you don't succeed, try try again. | |
309 const int kFallback[] = { | |
310 TEST_DIR_CANT_WRITE, | |
311 TEST_DIR_CANT_GET, | |
312 TEST_DIR_WORKS | |
313 }; | |
314 ClearScopedTempDir(sandboxed_unpacker_->temp_dir_); | |
315 EXPECT_CALL(*client_, OnUnpackFailure(_)).Times(0); | |
316 ASSERT_TRUE( | |
317 sandboxed_unpacker_->CreateTempDirectory( | |
318 kFallback, arraysize(kFallback))); | |
319 ASSERT_EQ( | |
320 dir_works.value(), | |
321 sandboxed_unpacker_->temp_dir_.path().DirName().value()); | |
322 } | |
OLD | NEW |