Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(342)

Side by Side Diff: mojo/shell/capability_filter_unittest.cc

Issue 1358533004: Move more of ContentHandler handling into PackageManager. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: . Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « mojo/shell/capability_filter_test.cc ('k') | mojo/shell/content_handler_connection.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 "base/at_exit.h" 5 #include "mojo/shell/capability_filter_test.h"
6 #include "base/bind.h"
7 #include "base/macros.h"
8 #include "base/memory/scoped_vector.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/stl_util.h"
11 #include "base/strings/stringprintf.h"
12 #include "mojo/application/public/cpp/application_connection.h"
13 #include "mojo/application/public/cpp/application_delegate.h"
14 #include "mojo/application/public/cpp/application_impl.h"
15 #include "mojo/application/public/cpp/connect.h"
16 #include "mojo/application/public/cpp/interface_factory.h"
17 #include "mojo/application/public/cpp/service_provider_impl.h"
18 #include "mojo/application/public/interfaces/content_handler.mojom.h"
19 #include "mojo/common/weak_binding_set.h"
20 #include "mojo/public/cpp/bindings/strong_binding.h"
21 #include "mojo/shell/application_loader.h"
22 #include "mojo/shell/application_manager.h"
23 #include "mojo/shell/capability_filter_unittest.mojom.h"
24 #include "mojo/shell/test_package_manager.h" 6 #include "mojo/shell/test_package_manager.h"
25 #include "testing/gtest/include/gtest/gtest.h" 7 #include "testing/gtest/include/gtest/gtest.h"
26 8
27 namespace mojo { 9 namespace mojo {
28 namespace shell { 10 namespace shell {
29 namespace { 11 namespace test {
30 12
31 const char kTestMimeType[] = "test/mime-type"; 13 class CapabilityFilterApplicationTest : public CapabilityFilterTest {
32
33 // Lives on the main thread of the test.
34 // Listens for services exposed/blocked and for application connections being
35 // closed. Quits |loop| when all expectations are met.
36 class ConnectionValidator : public ApplicationLoader,
37 public ApplicationDelegate,
38 public InterfaceFactory<Validator>,
39 public Validator {
40 public: 14 public:
41 ConnectionValidator(const std::set<std::string>& expectations, 15 CapabilityFilterApplicationTest() {}
42 base::MessageLoop* loop) 16 ~CapabilityFilterApplicationTest() override {}
43 : app_(nullptr),
44 expectations_(expectations),
45 loop_(loop) {}
46 ~ConnectionValidator() override {}
47
48 bool expectations_met() {
49 return unexpected_.empty() && expectations_.empty();
50 }
51
52 void PrintUnmetExpectations() {
53 for (auto expectation : expectations_)
54 ADD_FAILURE() << "Unmet: " << expectation;
55 for (auto unexpected : unexpected_)
56 ADD_FAILURE() << "Unexpected: " << unexpected;
57 }
58
59 private:
60 // Overridden from ApplicationLoader:
61 void Load(const GURL& url, InterfaceRequest<Application> request) override {
62 app_.reset(new ApplicationImpl(this, request.Pass()));
63 }
64
65 // Overridden from ApplicationDelegate:
66 bool ConfigureIncomingConnection(ApplicationConnection* connection) override {
67 connection->AddService<Validator>(this);
68 return true;
69 }
70
71 // Overridden from InterfaceFactory<Validator>:
72 void Create(ApplicationConnection* connection,
73 InterfaceRequest<Validator> request) override {
74 validator_bindings_.AddBinding(this, request.Pass());
75 }
76
77 // Overridden from Validator:
78 void AddServiceCalled(const String& app_url,
79 const String& service_url,
80 const String& name,
81 bool blocked) override {
82 Validate(base::StringPrintf("%s %s %s %s",
83 blocked ? "B" : "E", app_url.data(), service_url.data(), name.data()));
84 }
85 void ConnectionClosed(const String& app_url,
86 const String& service_url) override {
87 Validate(base::StringPrintf("C %s %s", app_url.data(), service_url.data()));
88 }
89
90 void Validate(const std::string& result) {
91 DVLOG(1) << "Validate: " << result;
92 auto i = expectations_.find(result);
93 if (i != expectations_.end()) {
94 expectations_.erase(i);
95 if (expectations_.empty())
96 loop_->Quit();
97 } else {
98 // This is a test failure, and will result in PrintUnexpectedExpecations()
99 // being called.
100 unexpected_.insert(result);
101 loop_->Quit();
102 }
103 }
104
105 scoped_ptr<ApplicationImpl> app_;
106 std::set<std::string> expectations_;
107 std::set<std::string> unexpected_;
108 base::MessageLoop* loop_;
109 WeakBindingSet<Validator> validator_bindings_;
110
111 DISALLOW_COPY_AND_ASSIGN(ConnectionValidator);
112 };
113
114 // This class models an application who will use the shell to interact with a
115 // system service. The shell may limit this application's visibility of the full
116 // set of interfaces exposed by that service.
117 class TestApplication : public ApplicationDelegate {
118 public:
119 TestApplication() : app_(nullptr) {}
120 ~TestApplication() override {}
121
122 private:
123 // Overridden from ApplicationDelegate:
124 void Initialize(ApplicationImpl* app) override {
125 app_ = app;
126 }
127 bool ConfigureIncomingConnection(ApplicationConnection* connection) override {
128 // TestApplications receive their Validator via the inbound connection.
129 connection->ConnectToService(&validator_);
130
131 URLRequestPtr request(URLRequest::New());
132 request->url = String::From("test:service");
133 connection1_ = app_->ConnectToApplication(request.Pass());
134 connection1_->SetRemoteServiceProviderConnectionErrorHandler(
135 base::Bind(&TestApplication::ConnectionClosed,
136 base::Unretained(this), "test:service"));
137
138 URLRequestPtr request2(URLRequest::New());
139 request2->url = String::From("test:service2");
140 connection2_ = app_->ConnectToApplication(request2.Pass());
141 connection2_->SetRemoteServiceProviderConnectionErrorHandler(
142 base::Bind(&TestApplication::ConnectionClosed,
143 base::Unretained(this), "test:service2"));
144 return true;
145 }
146
147 void ConnectionClosed(const std::string& service_url) {
148 validator_->ConnectionClosed(app_->url(), service_url);
149 }
150
151 ApplicationImpl* app_;
152 ValidatorPtr validator_;
153 scoped_ptr<ApplicationConnection> connection1_;
154 scoped_ptr<ApplicationConnection> connection2_;
155
156 DISALLOW_COPY_AND_ASSIGN(TestApplication);
157 };
158
159 class TestContentHandler : public ApplicationDelegate,
160 public InterfaceFactory<ContentHandler>,
161 public ContentHandler {
162 public:
163 TestContentHandler() : app_(nullptr) {}
164 ~TestContentHandler() override {}
165
166 private:
167 // Overridden from ApplicationDelegate:
168 void Initialize(ApplicationImpl* app) override {
169 app_ = app;
170 }
171 bool ConfigureIncomingConnection(ApplicationConnection* connection) override {
172 connection->AddService<ContentHandler>(this);
173 return true;
174 }
175
176 // Overridden from InterfaceFactory<ContentHandler>:
177 void Create(ApplicationConnection* connection,
178 InterfaceRequest<ContentHandler> request) override {
179 bindings_.AddBinding(this, request.Pass());
180 }
181
182 // Overridden from ContentHandler:
183 void StartApplication(InterfaceRequest<Application> application,
184 URLResponsePtr response) override {
185 scoped_ptr<ApplicationDelegate> delegate(new TestApplication);
186 embedded_apps_.push_back(
187 new ApplicationImpl(delegate.get(), application.Pass()));
188 embedded_app_delegates_.push_back(delegate.Pass());
189 }
190
191 ApplicationImpl* app_;
192 WeakBindingSet<ContentHandler> bindings_;
193 ScopedVector<ApplicationDelegate> embedded_app_delegates_;
194 ScopedVector<ApplicationImpl> embedded_apps_;
195
196 DISALLOW_COPY_AND_ASSIGN(TestContentHandler);
197 };
198
199 // This class models a system service that exposes two interfaces, Safe and
200 // Unsafe. The interface Unsafe is not to be exposed to untrusted applications.
201 class ServiceApplication : public ApplicationDelegate,
202 public InterfaceFactory<Safe>,
203 public InterfaceFactory<Unsafe>,
204 public Safe,
205 public Unsafe {
206 public:
207 ServiceApplication() : app_(nullptr) {}
208 ~ServiceApplication() override {}
209
210 private:
211 // Overridden from ApplicationDelegate:
212 void Initialize(ApplicationImpl* app) override {
213 app_ = app;
214 // ServiceApplications have no capability filter and can thus connect
215 // directly to the validator application.
216 URLRequestPtr request(URLRequest::New());
217 request->url = String::From("test:validator");
218 app_->ConnectToService(request.Pass(), &validator_);
219 }
220 bool ConfigureIncomingConnection(ApplicationConnection* connection) override {
221 AddService<Safe>(connection);
222 AddService<Unsafe>(connection);
223 return true;
224 }
225
226 // Overridden from InterfaceFactory<Safe>:
227 void Create(ApplicationConnection* connection,
228 InterfaceRequest<Safe> request) override {
229 safe_bindings_.AddBinding(this, request.Pass());
230 }
231
232 // Overridden from InterfaceFactory<Unsafe>:
233 void Create(ApplicationConnection* connection,
234 InterfaceRequest<Unsafe> request) override {
235 unsafe_bindings_.AddBinding(this, request.Pass());
236 }
237
238 template <typename Interface>
239 void AddService(ApplicationConnection* connection) {
240 validator_->AddServiceCalled(connection->GetRemoteApplicationURL(),
241 connection->GetConnectionURL(),
242 Interface::Name_,
243 !connection->AddService<Interface>(this));
244 }
245
246 ApplicationImpl* app_;
247 ValidatorPtr validator_;
248 WeakBindingSet<Safe> safe_bindings_;
249 WeakBindingSet<Unsafe> unsafe_bindings_;
250
251 DISALLOW_COPY_AND_ASSIGN(ServiceApplication);
252 };
253
254 // A custom Fetcher used to trigger a content handler for kTestMimeType for a
255 // specific test.
256 class TestFetcher : public Fetcher {
257 public:
258 TestFetcher(const GURL& url, const FetchCallback& callback)
259 : Fetcher(callback),
260 url_(url) {
261 loader_callback_.Run(make_scoped_ptr(this));
262 }
263 ~TestFetcher() override {}
264
265 private:
266 // Overridden from Fetcher:
267 const GURL& GetURL() const override { return url_; }
268 GURL GetRedirectURL() const override { return GURL(); }
269 GURL GetRedirectReferer() const override { return GURL(); }
270 URLResponsePtr AsURLResponse(base::TaskRunner* task_runner,
271 uint32_t skip) override {
272 URLResponsePtr response(URLResponse::New());
273 response->url = url_.spec();
274 return response.Pass();
275 }
276 void AsPath(
277 base::TaskRunner* task_runner,
278 base::Callback<void(const base::FilePath&, bool)> callback) override {}
279 std::string MimeType() override { return kTestMimeType; }
280 bool HasMojoMagic() override { return false; }
281 bool PeekFirstLine(std::string* line) override { return false; }
282
283 const GURL url_;
284
285 DISALLOW_COPY_AND_ASSIGN(TestFetcher);
286 };
287
288 class CFTestPackageManager : public TestPackageManager {
289 public:
290 CFTestPackageManager() {}
291 ~CFTestPackageManager() override {}
292
293 void set_use_test_fetcher(bool use_test_fetcher) {
294 use_test_fetcher_ = use_test_fetcher;
295 }
296
297 private:
298 // Overridden from TestPackageManager:
299 void FetchRequest(URLRequestPtr request,
300 const Fetcher::FetchCallback& loader_callback) override {
301 if (use_test_fetcher_)
302 new TestFetcher(GURL(request->url), loader_callback);
303 }
304
305 bool use_test_fetcher_;
306
307 DISALLOW_COPY_AND_ASSIGN(CFTestPackageManager);
308 };
309
310 class TestLoader : public ApplicationLoader {
311 public:
312 explicit TestLoader(ApplicationDelegate* delegate) : delegate_(delegate) {}
313 ~TestLoader() override {}
314
315 private:
316 // Overridden from ApplicationLoader:
317 void Load(const GURL& url, InterfaceRequest<Application> request) override {
318 app_.reset(new ApplicationImpl(delegate_.get(), request.Pass()));
319 }
320
321 scoped_ptr<ApplicationDelegate> delegate_;
322 scoped_ptr<ApplicationImpl> app_;
323
324 DISALLOW_COPY_AND_ASSIGN(TestLoader);
325 };
326
327 class CapabilityFilterTest : public testing::Test {
328 public:
329 CapabilityFilterTest()
330 : test_package_manager_(nullptr),
331 validator_(nullptr) {}
332 ~CapabilityFilterTest() override {}
333
334 protected:
335 void RunApplication(const std::string& url, const CapabilityFilter& filter) {
336 ServiceProviderPtr services;
337
338 // We expose Validator to the test application via ConnectToApplication
339 // because we don't allow the test application to connect to test:validator.
340 // Adding it to the CapabilityFilter would interfere with the test.
341 ServiceProviderPtr exposed_services;
342 (new ServiceProviderImpl(GetProxy(&exposed_services)))->
343 AddService<Validator>(validator_);
344 scoped_ptr<ConnectToApplicationParams> params(
345 new ConnectToApplicationParams);
346 params->SetTarget(Identity(GURL(url), std::string(), filter));
347 params->set_services(GetProxy(&services));
348 params->set_exposed_services(exposed_services.Pass());
349 params->set_on_application_end(base::MessageLoop::QuitWhenIdleClosure());
350 application_manager_->ConnectToApplication(params.Pass());
351 }
352
353 void InitValidator(const std::set<std::string>& expectations) {
354 validator_ = new ConnectionValidator(expectations, &loop_);
355 application_manager()->SetLoaderForURL(make_scoped_ptr(validator_),
356 GURL("test:validator"));
357 }
358
359 template <class T>
360 void CreateLoader(const std::string& url) {
361 application_manager_->SetLoaderForURL(
362 make_scoped_ptr(new TestLoader(new T)), GURL(url));
363 }
364
365 virtual void RunTest() {
366 loop()->Run();
367 EXPECT_TRUE(validator_->expectations_met());
368 if (!validator_->expectations_met())
369 validator_->PrintUnmetExpectations();
370 }
371
372 void RunContentHandlerTest() {
373 set_use_test_fetcher();
374
375 GURL content_handler_url("test:content_handler");
376 test_package_manager_->RegisterContentHandler(kTestMimeType,
377 content_handler_url);
378
379 CreateLoader<TestContentHandler>(content_handler_url.spec());
380 RunTest();
381 }
382
383 base::MessageLoop* loop() { return &loop_; }
384 ApplicationManager* application_manager() {
385 return application_manager_.get();
386 }
387 ConnectionValidator* validator() { return validator_; }
388 void set_use_test_fetcher() {
389 test_package_manager_->set_use_test_fetcher(true);
390 }
391
392 // Overridden from testing::Test:
393 void SetUp() override {
394 test_package_manager_ = new CFTestPackageManager;
395 application_manager_.reset(
396 new ApplicationManager(make_scoped_ptr(test_package_manager_)));
397 CreateLoader<ServiceApplication>("test:service");
398 CreateLoader<ServiceApplication>("test:service2");
399 }
400 void TearDown() override {
401 test_package_manager_->set_use_test_fetcher(false);
402 application_manager_.reset();
403 }
404
405 private:
406 template<class T>
407 scoped_ptr<ApplicationDelegate> CreateApplicationDelegate() {
408 return scoped_ptr<ApplicationDelegate>(new T);
409 }
410
411 CFTestPackageManager* test_package_manager_;
412 base::ShadowingAtExitManager at_exit_;
413 base::MessageLoop loop_;
414 scoped_ptr<ApplicationManager> application_manager_;
415 ConnectionValidator* validator_;
416
417 DISALLOW_COPY_AND_ASSIGN(CapabilityFilterTest);
418 };
419
420 class CapabilityFilter_BlockingTest : public CapabilityFilterTest {
421 public:
422 CapabilityFilter_BlockingTest() {}
423 ~CapabilityFilter_BlockingTest() override {}
424
425 protected:
426 void RunTest() override {
427 // This first application can only connect to test:service. Connections to
428 // test:service2 will be blocked. It also will only be able to see the
429 // "Safe" interface exposed by test:service. It will be blocked from seeing
430 // "Unsafe".
431 AllowedInterfaces interfaces;
432 interfaces.insert(Safe::Name_);
433 CapabilityFilter filter;
434 filter["test:service"] = interfaces;
435 RunApplication("test:untrusted", filter);
436
437 // This second application can connect to both test:service and
438 // test:service2. It can connect to both "Safe" and "Unsafe" interfaces.
439 RunApplication("test:trusted", GetPermissiveCapabilityFilter());
440
441 CapabilityFilterTest::RunTest();
442 }
443 17
444 private: 18 private:
445 // Overridden from CapabilityFilterTest: 19 // Overridden from CapabilityFilterTest:
446 void SetUp() override { 20 PackageManager* CreatePackageManager() override {
447 CapabilityFilterTest::SetUp(); 21 return new TestPackageManager;
448
449 std::set<std::string> expectations;
450 expectations.insert("E test:trusted test:service mojo::shell::Safe");
451 expectations.insert("E test:trusted test:service mojo::shell::Unsafe");
452 expectations.insert("E test:trusted test:service2 mojo::shell::Safe");
453 expectations.insert("E test:trusted test:service2 mojo::shell::Unsafe");
454 expectations.insert("E test:untrusted test:service mojo::shell::Safe");
455 expectations.insert("B test:untrusted test:service mojo::shell::Unsafe");
456 expectations.insert("C test:untrusted test:service2");
457 InitValidator(expectations);
458 } 22 }
459 23
460 DISALLOW_COPY_AND_ASSIGN(CapabilityFilter_BlockingTest); 24 DISALLOW_COPY_AND_ASSIGN(CapabilityFilterApplicationTest);
461 }; 25 };
462 26
463 TEST_F(CapabilityFilter_BlockingTest, Application) { 27 TEST_F(CapabilityFilterApplicationTest, Blocking) {
464 CreateLoader<TestApplication>("test:trusted"); 28 CreateLoader<TestApplication>("test:trusted");
465 CreateLoader<TestApplication>("test:untrusted"); 29 CreateLoader<TestApplication>("test:untrusted");
466 RunTest(); 30 RunBlockingTest();
467 } 31 }
468 32
469 TEST_F(CapabilityFilter_BlockingTest, ContentHandler) { 33 TEST_F(CapabilityFilterApplicationTest, Wildcards) {
470 RunContentHandlerTest();
471 }
472
473 class CapabilityFilter_WildcardsTest : public CapabilityFilterTest {
474 public:
475 CapabilityFilter_WildcardsTest() {}
476 ~CapabilityFilter_WildcardsTest() override {}
477
478 protected:
479 void RunTest() override {
480 // This application is allowed to connect to any application because of a
481 // wildcard rule, and any interface exposed because of a wildcard rule in
482 // the interface array.
483 RunApplication("test:wildcard", GetPermissiveCapabilityFilter());
484
485 // This application is allowed to connect to no other applications because
486 // of an empty capability filter.
487 RunApplication("test:blocked", CapabilityFilter());
488
489 // This application is allowed to connect to any application because of a
490 // wildcard rule but may not connect to any interfaces because of an empty
491 // interface array.
492 CapabilityFilter filter1;
493 filter1["*"] = AllowedInterfaces();
494 RunApplication("test:wildcard2", filter1);
495
496 // This application is allowed to connect to both test:service and
497 // test:service2, and may see any interface exposed by test:service but only
498 // the Safe interface exposed by test:service2.
499 AllowedInterfaces interfaces2;
500 interfaces2.insert("*");
501 CapabilityFilter filter2;
502 filter2["test:service"] = interfaces2;
503 AllowedInterfaces interfaces3;
504 interfaces3.insert(Safe::Name_);
505 filter2["test:service2"] = interfaces3;
506 RunApplication("test:wildcard3", filter2);
507
508 CapabilityFilterTest::RunTest();
509 }
510
511 private:
512 // Overridden from CapabilityFilterTest:
513 void SetUp() override {
514 CapabilityFilterTest::SetUp();
515
516 std::set<std::string> expectations;
517 expectations.insert("E test:wildcard test:service mojo::shell::Safe");
518 expectations.insert("E test:wildcard test:service mojo::shell::Unsafe");
519 expectations.insert("E test:wildcard test:service2 mojo::shell::Safe");
520 expectations.insert("E test:wildcard test:service2 mojo::shell::Unsafe");
521 expectations.insert("C test:blocked test:service");
522 expectations.insert("C test:blocked test:service2");
523 expectations.insert("B test:wildcard2 test:service mojo::shell::Safe");
524 expectations.insert("B test:wildcard2 test:service mojo::shell::Unsafe");
525 expectations.insert("B test:wildcard2 test:service2 mojo::shell::Safe");
526 expectations.insert("B test:wildcard2 test:service2 mojo::shell::Unsafe");
527 expectations.insert("E test:wildcard3 test:service mojo::shell::Safe");
528 expectations.insert("E test:wildcard3 test:service mojo::shell::Unsafe");
529 expectations.insert("E test:wildcard3 test:service2 mojo::shell::Safe");
530 expectations.insert("B test:wildcard3 test:service2 mojo::shell::Unsafe");
531 InitValidator(expectations);
532 }
533
534 DISALLOW_COPY_AND_ASSIGN(CapabilityFilter_WildcardsTest);
535 };
536
537 TEST_F(CapabilityFilter_WildcardsTest, Application) {
538 CreateLoader<TestApplication>("test:wildcard"); 34 CreateLoader<TestApplication>("test:wildcard");
539 CreateLoader<TestApplication>("test:blocked"); 35 CreateLoader<TestApplication>("test:blocked");
540 CreateLoader<TestApplication>("test:wildcard2"); 36 CreateLoader<TestApplication>("test:wildcard2");
541 CreateLoader<TestApplication>("test:wildcard3"); 37 CreateLoader<TestApplication>("test:wildcard3");
542 RunTest(); 38 RunWildcardTest();
543 } 39 }
544 40
545 TEST_F(CapabilityFilter_WildcardsTest, ContentHandler) { 41 } // namespace test
546 RunContentHandlerTest();
547 }
548
549 } // namespace
550 } // namespace shell 42 } // namespace shell
551 } // namespace mojo 43 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/shell/capability_filter_test.cc ('k') | mojo/shell/content_handler_connection.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698