Roll src/third_party/skia d32087a:1052f51
[chromium-blink-merge.git] / mojo / shell / capability_filter_unittest.cc
blob1dbc35b168a3e31608f9647291ea154477fe35b6
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
3 // found in the LICENSE file.
5 #include "base/at_exit.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"
25 #include "testing/gtest/include/gtest/gtest.h"
27 namespace mojo {
28 namespace shell {
29 namespace {
31 const char kTestMimeType[] = "test/mime-type";
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:
41 ConnectionValidator(const std::set<std::string>& expectations,
42 base::MessageLoop* loop)
43 : app_(nullptr),
44 expectations_(expectations),
45 loop_(loop) {}
46 ~ConnectionValidator() override {}
48 bool expectations_met() {
49 return unexpected_.empty() && expectations_.empty();
52 void PrintUnmetExpectations() {
53 for (auto expectation : expectations_)
54 ADD_FAILURE() << "Unmet: " << expectation;
55 for (auto unexpected : unexpected_)
56 ADD_FAILURE() << "Unexpected: " << unexpected;
59 private:
60 // Overridden from ApplicationLoader:
61 void Load(const GURL& url, InterfaceRequest<Application> request) override {
62 app_.reset(new ApplicationImpl(this, request.Pass()));
65 // Overridden from ApplicationDelegate:
66 bool ConfigureIncomingConnection(ApplicationConnection* connection) override {
67 connection->AddService<Validator>(this);
68 return true;
71 // Overridden from InterfaceFactory<Validator>:
72 void Create(ApplicationConnection* connection,
73 InterfaceRequest<Validator> request) override {
74 validator_bindings_.AddBinding(this, request.Pass());
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()));
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()));
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();
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_;
111 DISALLOW_COPY_AND_ASSIGN(ConnectionValidator);
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 {}
122 private:
123 // Overridden from ApplicationDelegate:
124 void Initialize(ApplicationImpl* app) override {
125 app_ = app;
127 bool ConfigureIncomingConnection(ApplicationConnection* connection) override {
128 // TestApplications receive their Validator via the inbound connection.
129 connection->ConnectToService(&validator_);
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"));
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;
147 void ConnectionClosed(const std::string& service_url) {
148 validator_->ConnectionClosed(app_->url(), service_url);
151 ApplicationImpl* app_;
152 ValidatorPtr validator_;
153 scoped_ptr<ApplicationConnection> connection1_;
154 scoped_ptr<ApplicationConnection> connection2_;
156 DISALLOW_COPY_AND_ASSIGN(TestApplication);
159 class TestContentHandler : public ApplicationDelegate,
160 public InterfaceFactory<ContentHandler>,
161 public ContentHandler {
162 public:
163 TestContentHandler() : app_(nullptr) {}
164 ~TestContentHandler() override {}
166 private:
167 // Overridden from ApplicationDelegate:
168 void Initialize(ApplicationImpl* app) override {
169 app_ = app;
171 bool ConfigureIncomingConnection(ApplicationConnection* connection) override {
172 connection->AddService<ContentHandler>(this);
173 return true;
176 // Overridden from InterfaceFactory<ContentHandler>:
177 void Create(ApplicationConnection* connection,
178 InterfaceRequest<ContentHandler> request) override {
179 bindings_.AddBinding(this, request.Pass());
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());
191 ApplicationImpl* app_;
192 WeakBindingSet<ContentHandler> bindings_;
193 ScopedVector<ApplicationDelegate> embedded_app_delegates_;
194 ScopedVector<ApplicationImpl> embedded_apps_;
196 DISALLOW_COPY_AND_ASSIGN(TestContentHandler);
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 {}
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_);
220 bool ConfigureIncomingConnection(ApplicationConnection* connection) override {
221 AddService<Safe>(connection);
222 AddService<Unsafe>(connection);
223 return true;
226 // Overridden from InterfaceFactory<Safe>:
227 void Create(ApplicationConnection* connection,
228 InterfaceRequest<Safe> request) override {
229 safe_bindings_.AddBinding(this, request.Pass());
232 // Overridden from InterfaceFactory<Unsafe>:
233 void Create(ApplicationConnection* connection,
234 InterfaceRequest<Unsafe> request) override {
235 unsafe_bindings_.AddBinding(this, request.Pass());
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));
246 ApplicationImpl* app_;
247 ValidatorPtr validator_;
248 WeakBindingSet<Safe> safe_bindings_;
249 WeakBindingSet<Unsafe> unsafe_bindings_;
251 DISALLOW_COPY_AND_ASSIGN(ServiceApplication);
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));
263 ~TestFetcher() override {}
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();
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; }
283 const GURL url_;
285 DISALLOW_COPY_AND_ASSIGN(TestFetcher);
288 class CFTestPackageManager : public TestPackageManager {
289 public:
290 CFTestPackageManager() {}
291 ~CFTestPackageManager() override {}
293 void set_use_test_fetcher(bool use_test_fetcher) {
294 use_test_fetcher_ = use_test_fetcher;
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);
305 bool use_test_fetcher_;
307 DISALLOW_COPY_AND_ASSIGN(CFTestPackageManager);
310 class TestLoader : public ApplicationLoader {
311 public:
312 explicit TestLoader(ApplicationDelegate* delegate) : delegate_(delegate) {}
313 ~TestLoader() override {}
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()));
321 scoped_ptr<ApplicationDelegate> delegate_;
322 scoped_ptr<ApplicationImpl> app_;
324 DISALLOW_COPY_AND_ASSIGN(TestLoader);
327 class CapabilityFilterTest : public testing::Test {
328 public:
329 CapabilityFilterTest()
330 : test_package_manager_(nullptr),
331 validator_(nullptr) {}
332 ~CapabilityFilterTest() override {}
334 protected:
335 void RunApplication(const std::string& url, const CapabilityFilter& filter) {
336 ServiceProviderPtr services;
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 URLRequestPtr request(URLRequest::New());
345 request->url = String::From(url);
347 scoped_ptr<ConnectToApplicationParams> params(
348 new ConnectToApplicationParams);
349 params->SetURLInfo(request.Pass());
350 params->set_services(GetProxy(&services));
351 params->set_exposed_services(exposed_services.Pass());
352 params->set_filter(filter);
353 params->set_on_application_end(base::MessageLoop::QuitWhenIdleClosure());
354 application_manager_->ConnectToApplication(params.Pass());
357 void InitValidator(const std::set<std::string>& expectations) {
358 validator_ = new ConnectionValidator(expectations, &loop_);
359 application_manager()->SetLoaderForURL(make_scoped_ptr(validator_),
360 GURL("test:validator"));
363 template <class T>
364 void CreateLoader(const std::string& url) {
365 application_manager_->SetLoaderForURL(
366 make_scoped_ptr(new TestLoader(new T)), GURL(url));
369 virtual void RunTest() {
370 loop()->Run();
371 EXPECT_TRUE(validator_->expectations_met());
372 if (!validator_->expectations_met())
373 validator_->PrintUnmetExpectations();
376 void RunContentHandlerTest() {
377 set_use_test_fetcher();
379 GURL content_handler_url("test:content_handler");
380 test_package_manager_->RegisterContentHandler(kTestMimeType,
381 content_handler_url);
383 CreateLoader<TestContentHandler>(content_handler_url.spec());
384 RunTest();
387 base::MessageLoop* loop() { return &loop_; }
388 ApplicationManager* application_manager() {
389 return application_manager_.get();
391 ConnectionValidator* validator() { return validator_; }
392 void set_use_test_fetcher() {
393 test_package_manager_->set_use_test_fetcher(true);
396 // Overridden from testing::Test:
397 void SetUp() override {
398 test_package_manager_ = new CFTestPackageManager;
399 application_manager_.reset(
400 new ApplicationManager(make_scoped_ptr(test_package_manager_)));
401 CreateLoader<ServiceApplication>("test:service");
402 CreateLoader<ServiceApplication>("test:service2");
404 void TearDown() override {
405 application_manager_.reset();
406 test_package_manager_->set_use_test_fetcher(false);
409 private:
410 template<class T>
411 scoped_ptr<ApplicationDelegate> CreateApplicationDelegate() {
412 return scoped_ptr<ApplicationDelegate>(new T);
415 CFTestPackageManager* test_package_manager_;
416 base::ShadowingAtExitManager at_exit_;
417 base::MessageLoop loop_;
418 scoped_ptr<ApplicationManager> application_manager_;
419 ConnectionValidator* validator_;
421 DISALLOW_COPY_AND_ASSIGN(CapabilityFilterTest);
424 class CapabilityFilter_BlockingTest : public CapabilityFilterTest {
425 public:
426 CapabilityFilter_BlockingTest() {}
427 ~CapabilityFilter_BlockingTest() override {}
429 protected:
430 void RunTest() override {
431 // This first application can only connect to test:service. Connections to
432 // test:service2 will be blocked. It also will only be able to see the
433 // "Safe" interface exposed by test:service. It will be blocked from seeing
434 // "Unsafe".
435 AllowedInterfaces interfaces;
436 interfaces.insert(Safe::Name_);
437 CapabilityFilter filter;
438 filter["test:service"] = interfaces;
439 RunApplication("test:untrusted", filter);
441 // This second application can connect to both test:service and
442 // test:service2. It can connect to both "Safe" and "Unsafe" interfaces.
443 RunApplication("test:trusted", GetPermissiveCapabilityFilter());
445 CapabilityFilterTest::RunTest();
448 private:
449 // Overridden from CapabilityFilterTest:
450 void SetUp() override {
451 CapabilityFilterTest::SetUp();
453 std::set<std::string> expectations;
454 expectations.insert("E test:trusted test:service mojo::shell::Safe");
455 expectations.insert("E test:trusted test:service mojo::shell::Unsafe");
456 expectations.insert("E test:trusted test:service2 mojo::shell::Safe");
457 expectations.insert("E test:trusted test:service2 mojo::shell::Unsafe");
458 expectations.insert("E test:untrusted test:service mojo::shell::Safe");
459 expectations.insert("B test:untrusted test:service mojo::shell::Unsafe");
460 expectations.insert("C test:untrusted test:service2");
461 InitValidator(expectations);
464 DISALLOW_COPY_AND_ASSIGN(CapabilityFilter_BlockingTest);
467 TEST_F(CapabilityFilter_BlockingTest, Application) {
468 CreateLoader<TestApplication>("test:trusted");
469 CreateLoader<TestApplication>("test:untrusted");
470 RunTest();
473 TEST_F(CapabilityFilter_BlockingTest, ContentHandler) {
474 RunContentHandlerTest();
477 class CapabilityFilter_WildcardsTest : public CapabilityFilterTest {
478 public:
479 CapabilityFilter_WildcardsTest() {}
480 ~CapabilityFilter_WildcardsTest() override {}
482 protected:
483 void RunTest() override {
484 // This application is allowed to connect to any application because of a
485 // wildcard rule, and any interface exposed because of a wildcard rule in
486 // the interface array.
487 RunApplication("test:wildcard", GetPermissiveCapabilityFilter());
489 // This application is allowed to connect to no other applications because
490 // of an empty capability filter.
491 RunApplication("test:blocked", CapabilityFilter());
493 // This application is allowed to connect to any application because of a
494 // wildcard rule but may not connect to any interfaces because of an empty
495 // interface array.
496 CapabilityFilter filter1;
497 filter1["*"] = AllowedInterfaces();
498 RunApplication("test:wildcard2", filter1);
500 // This application is allowed to connect to both test:service and
501 // test:service2, and may see any interface exposed by test:service but only
502 // the Safe interface exposed by test:service2.
503 AllowedInterfaces interfaces2;
504 interfaces2.insert("*");
505 CapabilityFilter filter2;
506 filter2["test:service"] = interfaces2;
507 AllowedInterfaces interfaces3;
508 interfaces3.insert(Safe::Name_);
509 filter2["test:service2"] = interfaces3;
510 RunApplication("test:wildcard3", filter2);
512 CapabilityFilterTest::RunTest();
515 private:
516 // Overridden from CapabilityFilterTest:
517 void SetUp() override {
518 CapabilityFilterTest::SetUp();
520 std::set<std::string> expectations;
521 expectations.insert("E test:wildcard test:service mojo::shell::Safe");
522 expectations.insert("E test:wildcard test:service mojo::shell::Unsafe");
523 expectations.insert("E test:wildcard test:service2 mojo::shell::Safe");
524 expectations.insert("E test:wildcard test:service2 mojo::shell::Unsafe");
525 expectations.insert("C test:blocked test:service");
526 expectations.insert("C test:blocked test:service2");
527 expectations.insert("B test:wildcard2 test:service mojo::shell::Safe");
528 expectations.insert("B test:wildcard2 test:service mojo::shell::Unsafe");
529 expectations.insert("B test:wildcard2 test:service2 mojo::shell::Safe");
530 expectations.insert("B test:wildcard2 test:service2 mojo::shell::Unsafe");
531 expectations.insert("E test:wildcard3 test:service mojo::shell::Safe");
532 expectations.insert("E test:wildcard3 test:service mojo::shell::Unsafe");
533 expectations.insert("E test:wildcard3 test:service2 mojo::shell::Safe");
534 expectations.insert("B test:wildcard3 test:service2 mojo::shell::Unsafe");
535 InitValidator(expectations);
538 DISALLOW_COPY_AND_ASSIGN(CapabilityFilter_WildcardsTest);
541 TEST_F(CapabilityFilter_WildcardsTest, Application) {
542 CreateLoader<TestApplication>("test:wildcard");
543 CreateLoader<TestApplication>("test:blocked");
544 CreateLoader<TestApplication>("test:wildcard2");
545 CreateLoader<TestApplication>("test:wildcard3");
546 RunTest();
549 TEST_F(CapabilityFilter_WildcardsTest, ContentHandler) {
550 RunContentHandlerTest();
553 } // namespace
554 } // namespace shell
555 } // namespace mojo