OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2013 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/chromeos/extensions/device_local_account_external_polic y_loader.h" | |
6 | |
7 #include <string> | |
8 | |
9 #include "base/callback.h" | |
10 #include "base/file_util.h" | |
11 #include "base/files/scoped_temp_dir.h" | |
12 #include "base/message_loop/message_loop.h" | |
13 #include "base/message_loop/message_loop_proxy.h" | |
14 #include "base/path_service.h" | |
15 #include "base/run_loop.h" | |
16 #include "base/strings/stringprintf.h" | |
17 #include "base/values.h" | |
18 #include "base/version.h" | |
19 #include "chrome/browser/chrome_notification_types.h" | |
20 #include "chrome/browser/extensions/external_provider_impl.h" | |
21 #include "chrome/browser/extensions/external_provider_interface.h" | |
22 #include "chrome/browser/extensions/updater/extension_downloader.h" | |
23 #include "chrome/browser/policy/cloud/mock_cloud_policy_store.h" | |
24 #include "chrome/browser/policy/policy_map.h" | |
25 #include "chrome/browser/policy/policy_types.h" | |
26 #include "chrome/common/chrome_paths.h" | |
27 #include "chrome/common/extensions/extension.h" | |
28 #include "chrome/common/extensions/extension_constants.h" | |
29 #include "chrome/test/base/testing_browser_process.h" | |
30 #include "content/public/browser/notification_service.h" | |
31 #include "content/public/browser/notification_source.h" | |
32 #include "content/public/browser/render_process_host.h" | |
33 #include "content/public/test/test_browser_thread_bundle.h" | |
34 #include "content/public/test/test_utils.h" | |
35 #include "extensions/common/manifest.h" | |
36 #include "net/url_request/test_url_fetcher_factory.h" | |
37 #include "net/url_request/url_fetcher_delegate.h" | |
38 #include "net/url_request/url_request_context_getter.h" | |
39 #include "net/url_request/url_request_test_util.h" | |
40 #include "policy/policy_constants.h" | |
41 #include "testing/gmock/include/gmock/gmock.h" | |
42 #include "testing/gtest/include/gtest/gtest.h" | |
43 #include "url/gurl.h" | |
44 | |
45 using ::testing::InvokeWithoutArgs; | |
46 using ::testing::Mock; | |
47 using ::testing::_; | |
48 | |
49 namespace chromeos { | |
50 | |
51 namespace { | |
52 | |
53 const char kCacheDir[] = "cache"; | |
54 const char kExtensionId[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf"; | |
55 const char kExtensionUpdateManifest[] = | |
56 "extensions/good_v1_update_manifest.xml"; | |
57 const char kExtensionCRXSourceDir[] = "extensions"; | |
58 const char kExtensionCRXFile[] = "good.crx"; | |
59 const char kExtensionCRXVersion[] = "1.0.0.0"; | |
60 | |
61 class MockExternalPolicyProviderVisitor | |
62 : public extensions::ExternalProviderInterface::VisitorInterface { | |
63 public: | |
64 MockExternalPolicyProviderVisitor(); | |
65 virtual ~MockExternalPolicyProviderVisitor(); | |
66 | |
67 MOCK_METHOD6(OnExternalExtensionFileFound, | |
68 bool(const std::string&, | |
69 const base::Version*, | |
70 const base::FilePath&, | |
71 extensions::Manifest::Location, | |
72 int, | |
73 bool)); | |
74 MOCK_METHOD5(OnExternalExtensionUpdateUrlFound, | |
75 bool(const std::string&, | |
76 const GURL&, | |
77 extensions::Manifest::Location, | |
78 int, | |
79 bool)); | |
80 MOCK_METHOD1(OnExternalProviderReady, | |
81 void(const extensions::ExternalProviderInterface* provider)); | |
82 | |
83 private: | |
84 DISALLOW_COPY_AND_ASSIGN(MockExternalPolicyProviderVisitor); | |
85 }; | |
86 | |
87 MockExternalPolicyProviderVisitor::MockExternalPolicyProviderVisitor() { | |
88 } | |
89 | |
90 MockExternalPolicyProviderVisitor::~MockExternalPolicyProviderVisitor() { | |
91 } | |
92 | |
93 } // namespace | |
94 | |
95 class DeviceLocalAccountExternalPolicyLoaderTest : public testing::Test { | |
96 protected: | |
97 DeviceLocalAccountExternalPolicyLoaderTest(); | |
98 virtual ~DeviceLocalAccountExternalPolicyLoaderTest(); | |
99 | |
100 virtual void SetUp() OVERRIDE; | |
101 virtual void TearDown() OVERRIDE; | |
102 | |
103 void VerifyAndResetVisitorCallExpectations(); | |
104 void SetForceInstallListPolicy(); | |
105 | |
106 content::TestBrowserThreadBundle thread_bundle_; | |
Joao da Silva
2013/10/17 14:57:54
This probably won't be necessary if you just have
bartfab (slow)
2013/10/18 12:58:39
DeviceLocalAccountExternalPolicyLoader inherits fr
| |
107 base::ScopedTempDir temp_dir_; | |
108 base::FilePath cache_dir_; | |
Joao da Silva
2013/10/17 14:57:54
#include
bartfab (slow)
2013/10/18 12:58:39
Already included by device_local_account_external_
| |
109 policy::MockCloudPolicyStore store_; | |
110 scoped_refptr<net::URLRequestContextGetter> request_context_getter_; | |
111 base::FilePath test_dir_; | |
112 | |
113 scoped_refptr<DeviceLocalAccountExternalPolicyLoader> loader_; | |
114 MockExternalPolicyProviderVisitor visitor_; | |
115 scoped_ptr<extensions::ExternalProviderImpl> provider_; | |
116 }; | |
117 | |
118 DeviceLocalAccountExternalPolicyLoaderTest:: | |
119 DeviceLocalAccountExternalPolicyLoaderTest() | |
120 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) { | |
121 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | |
122 cache_dir_ = temp_dir_.path().Append(kCacheDir); | |
123 ASSERT_TRUE(file_util::CreateDirectoryAndGetError(cache_dir_, NULL)); | |
124 } | |
125 | |
126 DeviceLocalAccountExternalPolicyLoaderTest:: | |
127 ~DeviceLocalAccountExternalPolicyLoaderTest() { | |
128 } | |
129 | |
130 void DeviceLocalAccountExternalPolicyLoaderTest::SetUp() { | |
131 request_context_getter_ = | |
132 new net::TestURLRequestContextGetter(base::MessageLoopProxy::current()); | |
133 TestingBrowserProcess::GetGlobal()->SetSystemRequestContext( | |
134 request_context_getter_.get()); | |
135 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir_)); | |
136 | |
137 loader_ = new DeviceLocalAccountExternalPolicyLoader(&store_, cache_dir_); | |
138 provider_.reset(new extensions::ExternalProviderImpl( | |
139 &visitor_, | |
140 loader_, | |
141 NULL, | |
142 extensions::Manifest::EXTERNAL_POLICY, | |
143 extensions::Manifest::EXTERNAL_POLICY_DOWNLOAD, | |
144 extensions::Extension::NO_FLAGS)); | |
145 | |
146 content::RenderProcessHost::SetRunRendererInProcess(true); | |
Joao da Silva
2013/10/17 14:57:54
Why?
Joao da Silva
2013/10/17 14:57:54
Why?
bartfab (slow)
2013/10/18 12:58:39
Without this, the extension system would try to un
| |
147 | |
148 VerifyAndResetVisitorCallExpectations(); | |
149 } | |
150 | |
151 void DeviceLocalAccountExternalPolicyLoaderTest::TearDown() { | |
152 content::RenderProcessHost::SetRunRendererInProcess(false); | |
153 TestingBrowserProcess::GetGlobal()->SetSystemRequestContext(NULL); | |
154 } | |
155 | |
156 void DeviceLocalAccountExternalPolicyLoaderTest:: | |
157 VerifyAndResetVisitorCallExpectations() { | |
158 Mock::VerifyAndClearExpectations(&visitor_); | |
159 EXPECT_CALL(visitor_, OnExternalExtensionFileFound(_, _, _, _, _, _)) | |
160 .Times(0); | |
161 EXPECT_CALL(visitor_, OnExternalExtensionUpdateUrlFound(_, _, _, _, _)) | |
162 .Times(0); | |
163 EXPECT_CALL(visitor_, OnExternalProviderReady(_)) | |
164 .Times(0); | |
165 } | |
166 | |
167 void DeviceLocalAccountExternalPolicyLoaderTest::SetForceInstallListPolicy() { | |
168 scoped_ptr<base::ListValue> forcelist(new base::ListValue); | |
169 forcelist->AppendString("invalid"); | |
170 forcelist->AppendString(base::StringPrintf( | |
171 "%s;%s", | |
172 kExtensionId, | |
173 extension_urls::GetWebstoreUpdateUrl().spec().c_str())); | |
174 store_.policy_map_.Set(policy::key::kExtensionInstallForcelist, | |
175 policy::POLICY_LEVEL_MANDATORY, | |
176 policy::POLICY_SCOPE_USER, | |
177 forcelist.release(), | |
178 NULL); | |
179 store_.NotifyStoreLoaded(); | |
180 } | |
181 | |
182 // Verifies that when the cache is not explicitly started, the loader does not | |
183 // serve any extensions, even if the force-install list policy is set or a load | |
184 // is manually requested. | |
185 TEST_F(DeviceLocalAccountExternalPolicyLoaderTest, CacheNotStarted) { | |
186 // Set the force-install list policy. | |
187 SetForceInstallListPolicy(); | |
188 | |
189 // Manually request a load. | |
190 loader_->StartLoading(); | |
191 | |
192 EXPECT_FALSE(loader_->IsCacheRunning()); | |
193 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting()); | |
194 } | |
195 | |
196 // Verifies that the cache can be started and stopped correctly. | |
197 TEST_F(DeviceLocalAccountExternalPolicyLoaderTest, ForceInstallListEmpty) { | |
198 // Set an empty force-install list policy. | |
199 store_.NotifyStoreLoaded(); | |
200 | |
201 // Start the cache. Verify that the loader announces an empty extension list. | |
202 EXPECT_CALL(visitor_, OnExternalProviderReady(provider_.get())) | |
203 .Times(1); | |
204 loader_->StartCache(base::MessageLoopProxy::current()); | |
205 VerifyAndResetVisitorCallExpectations(); | |
206 | |
207 // Stop the cache. Verify that the loader announces an empty extension list. | |
208 EXPECT_CALL(visitor_, OnExternalProviderReady(provider_.get())) | |
209 .Times(1); | |
210 base::RunLoop run_loop; | |
211 loader_->StopCache(run_loop.QuitClosure()); | |
212 VerifyAndResetVisitorCallExpectations(); | |
213 | |
214 // Spin the loop until the cache shutdown callback is invoked. Verify that at | |
215 // that point, no further file I/O tasks are pending. | |
216 run_loop.Run(); | |
217 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting()); | |
218 } | |
219 | |
220 // Verifies that when a force-install list policy referencing an extension is | |
221 // set and the cache is started, the loader downloads, caches and serves the | |
222 // extension. | |
223 TEST_F(DeviceLocalAccountExternalPolicyLoaderTest, ForceInstallListSet) { | |
224 // Set a force-install list policy that contains an invalid entry (which | |
225 // should be ignored) and a valid reference to an extension. | |
226 SetForceInstallListPolicy(); | |
227 | |
228 // Start the cache. | |
229 loader_->StartCache(base::MessageLoopProxy::current()); | |
230 | |
231 // Spin the loop, allowing the loader to process the force-install list. | |
232 // Verify that the loader announces an empty extension list. | |
233 net::TestURLFetcherFactory factory; | |
234 EXPECT_CALL(visitor_, OnExternalProviderReady(provider_.get())) | |
235 .Times(1); | |
236 base::MessageLoop::current()->RunUntilIdle(); | |
237 | |
238 // Verify that a downloader has started and is attempting to download an | |
239 // update manifest. | |
240 net::TestURLFetcher* fetcher = factory.GetFetcherByID( | |
241 extensions::ExtensionDownloader::kManifestFetcherId); | |
242 ASSERT_TRUE(fetcher); | |
243 ASSERT_TRUE(fetcher->delegate()); | |
244 | |
245 // Return a manifest to the downloader. | |
246 std::string manifest; | |
247 EXPECT_TRUE(base::ReadFileToString(test_dir_.Append(kExtensionUpdateManifest), | |
248 &manifest)); | |
249 fetcher->set_response_code(200); | |
250 fetcher->SetResponseString(manifest); | |
251 fetcher->delegate()->OnURLFetchComplete(fetcher); | |
252 | |
253 // Wait for the manifest to be parsed. | |
254 content::WindowedNotificationObserver( | |
255 chrome::NOTIFICATION_EXTENSION_UPDATE_FOUND, | |
256 content::NotificationService::AllSources()).Wait(); | |
257 | |
258 // Verify that the downloader is attempting to download a CRX file. | |
259 fetcher = factory.GetFetcherByID( | |
260 extensions::ExtensionDownloader::kExtensionFetcherId); | |
261 ASSERT_TRUE(fetcher); | |
262 ASSERT_TRUE(fetcher->delegate()); | |
263 | |
264 // Create a temporary CRX file and return its path to the downloader. | |
265 EXPECT_TRUE(base::CopyFile( | |
266 test_dir_.Append(kExtensionCRXSourceDir).Append(kExtensionCRXFile), | |
267 temp_dir_.path().Append(kExtensionCRXFile))); | |
268 fetcher->set_response_code(200); | |
269 fetcher->SetResponseFilePath(temp_dir_.path().Append(kExtensionCRXFile)); | |
270 fetcher->delegate()->OnURLFetchComplete(fetcher); | |
271 | |
272 // Spin the loop. Verify that the loader announces the presence of a new CRX | |
273 // file, served from the cache directory. | |
274 const base::FilePath cached_crx_path = cache_dir_.Append(base::StringPrintf( | |
275 "%s-%s.crx", kExtensionId, kExtensionCRXVersion)); | |
276 base::RunLoop cache_run_loop; | |
277 EXPECT_CALL(visitor_, OnExternalExtensionFileFound( | |
278 kExtensionId, | |
279 _, | |
280 cached_crx_path, | |
281 extensions::Manifest::EXTERNAL_POLICY, | |
282 _, | |
283 _)); | |
284 EXPECT_CALL(visitor_, OnExternalProviderReady(provider_.get())) | |
285 .Times(1) | |
286 .WillOnce(InvokeWithoutArgs(&cache_run_loop, &base::RunLoop::Quit)); | |
287 cache_run_loop.Run(); | |
288 VerifyAndResetVisitorCallExpectations(); | |
289 | |
290 // Verify that the CRX file actually exists in the cache directory and its | |
291 // contents matches the file returned to the downloader. | |
292 EXPECT_TRUE(base::ContentsEqual( | |
293 test_dir_.Append(kExtensionCRXSourceDir).Append(kExtensionCRXFile), | |
294 cached_crx_path)); | |
295 | |
296 // Stop the cache. Verify that the loader announces an empty extension list. | |
297 EXPECT_CALL(visitor_, OnExternalProviderReady(provider_.get())) | |
298 .Times(1); | |
299 base::RunLoop shutdown_run_loop; | |
300 loader_->StopCache(shutdown_run_loop.QuitClosure()); | |
301 VerifyAndResetVisitorCallExpectations(); | |
302 | |
303 // Spin the loop until the cache shutdown callback is invoked. Verify that at | |
304 // that point, no further file I/O tasks are pending. | |
305 shutdown_run_loop.Run(); | |
306 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting()); | |
307 } | |
Joao da Silva
2013/10/17 14:57:54
nice test
| |
308 | |
309 } // namespace chromeos | |
OLD | NEW |