Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
|
sky
2015/07/22 15:57:45
2015
| |
| 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 "base/at_exit.h" | |
| 6 #include "base/bind.h" | |
| 7 #include "base/macros.h" | |
| 8 #include "base/message_loop/message_loop.h" | |
| 9 #include "base/strings/stringprintf.h" | |
| 10 #include "mojo/application/public/cpp/application_connection.h" | |
| 11 #include "mojo/application/public/cpp/application_delegate.h" | |
| 12 #include "mojo/application/public/cpp/application_impl.h" | |
| 13 #include "mojo/application/public/cpp/connect.h" | |
| 14 #include "mojo/application/public/cpp/interface_factory.h" | |
| 15 #include "mojo/common/weak_binding_set.h" | |
| 16 #include "mojo/public/cpp/bindings/strong_binding.h" | |
| 17 #include "mojo/shell/application_loader.h" | |
| 18 #include "mojo/shell/application_manager.h" | |
| 19 #include "mojo/shell/test.mojom.h" | |
| 20 #include "testing/gtest/include/gtest/gtest.h" | |
| 21 | |
| 22 namespace mojo { | |
| 23 namespace shell { | |
| 24 namespace { | |
| 25 | |
| 26 // Quits |loop| when either: | |
| 27 // - all of the |valid_calls| are received, or | |
| 28 // - one of the |invalid_calls| is received. | |
| 29 class CallValidator { | |
| 30 public: | |
| 31 CallValidator(base::MessageLoop* loop, | |
| 32 const std::set<std::string>& valid_calls, | |
| 33 const std::set<std::string>& invalid_calls) | |
| 34 : loop_(loop), | |
| 35 valid_calls_(valid_calls), | |
| 36 invalid_calls_(invalid_calls) { | |
| 37 } | |
| 38 | |
| 39 static std::string FormatCall(const std::string& function, | |
| 40 const std::string& service_url, | |
| 41 const std::string& remote_url) { | |
| 42 return base::StringPrintf("%s %s %s", function.c_str(), service_url.c_str(), | |
| 43 remote_url.c_str()); | |
| 44 } | |
| 45 | |
| 46 void Call(const std::string& function, | |
| 47 const std::string& service_url, | |
| 48 const std::string& remote_url) { | |
| 49 std::string call = FormatCall(function, service_url, remote_url); | |
| 50 { | |
| 51 auto i = invalid_calls_.find(call); | |
| 52 if (i != invalid_calls_.end()) { | |
| 53 loop_->Quit(); | |
| 54 return; | |
| 55 } | |
| 56 } | |
| 57 | |
| 58 { | |
| 59 auto i = valid_calls_.find(call); | |
| 60 if (i != valid_calls_.end()) | |
| 61 valid_calls_.erase(i); | |
| 62 if (valid_calls_.empty()) | |
| 63 loop_->Quit(); | |
| 64 } | |
| 65 } | |
| 66 | |
| 67 bool called_all_valid() const { return valid_calls_.empty(); } | |
| 68 | |
| 69 private: | |
| 70 base::MessageLoop* loop_; | |
| 71 std::set<std::string> valid_calls_; | |
| 72 std::set<std::string> invalid_calls_; | |
| 73 | |
| 74 DISALLOW_COPY_AND_ASSIGN(CallValidator); | |
| 75 }; | |
| 76 | |
| 77 // This class models an application who will use the shell to interact with a | |
| 78 // system service. The shell may limit this application's visibility of the full | |
| 79 // set of interfaces exposed by that service. | |
| 80 class TestApplication : public ApplicationDelegate, | |
| 81 public ApplicationLoader, | |
| 82 public InterfaceFactory<Driver>, | |
| 83 public Driver { | |
| 84 public: | |
| 85 explicit TestApplication(bool connect_to_test_service_2) | |
| 86 : connect_to_test_service_2_(connect_to_test_service_2) {} | |
| 87 ~TestApplication() override {} | |
| 88 | |
| 89 private: | |
| 90 // Overridden from ApplicationDelegate: | |
| 91 bool ConfigureIncomingConnection(ApplicationConnection* connection) override { | |
| 92 connection->AddService<Driver>(this); | |
| 93 return true; | |
| 94 } | |
| 95 | |
| 96 // Overridden from ApplicationLoader: | |
| 97 void Load(const GURL& url, InterfaceRequest<Application> request) override { | |
| 98 app_.reset(new ApplicationImpl(this, request.Pass())); | |
| 99 } | |
| 100 | |
| 101 // Overridden from InterfaceFactory<Driver>: | |
| 102 void Create(ApplicationConnection* connection, | |
| 103 InterfaceRequest<Driver> request) override { | |
| 104 driver_bindings_.AddBinding(this, request.Pass()); | |
| 105 } | |
| 106 | |
| 107 // Overridden from Driver: | |
| 108 void Run() override { | |
| 109 URLRequestPtr request(URLRequest::New()); | |
| 110 request->url = String::From("test:service"); | |
| 111 ApplicationConnection* connection = | |
| 112 app_->ConnectToApplication(request.Pass()); | |
| 113 connection->ConnectToService(&safe_); | |
| 114 safe_->SafeMethod(); | |
| 115 connection->ConnectToService(&unsafe_); | |
| 116 unsafe_->UnsafeMethod(); | |
| 117 | |
| 118 if (connect_to_test_service_2_) { | |
| 119 URLRequestPtr request2(URLRequest::New()); | |
| 120 request2->url = String::From("test:service2"); | |
| 121 ApplicationConnection* connection2 = | |
| 122 app_->ConnectToApplication(request2.Pass()); | |
| 123 connection2->ConnectToService(&safe_2_); | |
| 124 safe_2_->SafeMethod(); | |
| 125 connection2->ConnectToService(&unsafe_2_); | |
| 126 unsafe_2_->UnsafeMethod(); | |
| 127 | |
| 128 } | |
| 129 } | |
| 130 | |
| 131 bool connect_to_test_service_2_; | |
| 132 scoped_ptr<ApplicationImpl> app_; | |
| 133 WeakBindingSet<Driver> driver_bindings_; | |
| 134 SafePtr safe_; | |
| 135 UnsafePtr unsafe_; | |
| 136 SafePtr safe_2_; | |
| 137 UnsafePtr unsafe_2_; | |
| 138 | |
| 139 DISALLOW_COPY_AND_ASSIGN(TestApplication); | |
| 140 }; | |
| 141 | |
| 142 class SafeImpl : public Safe { | |
| 143 public: | |
| 144 SafeImpl(CallValidator* validator, | |
| 145 const std::string& service_url, | |
| 146 const std::string& remote_url, | |
| 147 InterfaceRequest<Safe> request) | |
| 148 : validator_(validator), | |
| 149 service_url_(service_url), | |
| 150 remote_url_(remote_url), | |
| 151 binding_(this, request.Pass()) {} | |
| 152 ~SafeImpl() override {} | |
| 153 | |
| 154 private: | |
| 155 // Overridden from Safe: | |
| 156 virtual void SafeMethod() override { | |
| 157 validator_->Call("SafeMethod", service_url_, remote_url_); | |
| 158 } | |
| 159 | |
| 160 CallValidator* validator_; | |
| 161 std::string service_url_; | |
| 162 std::string remote_url_; | |
| 163 StrongBinding<Safe> binding_; | |
| 164 | |
| 165 DISALLOW_COPY_AND_ASSIGN(SafeImpl); | |
| 166 }; | |
| 167 | |
| 168 class UnsafeImpl : public Unsafe { | |
| 169 public: | |
| 170 UnsafeImpl(CallValidator* validator, | |
| 171 const std::string& service_url, | |
| 172 const std::string& remote_url, | |
| 173 InterfaceRequest<Unsafe> request) | |
| 174 : validator_(validator), | |
| 175 service_url_(service_url), | |
| 176 remote_url_(remote_url), | |
| 177 binding_(this, request.Pass()) {} | |
| 178 ~UnsafeImpl() override {} | |
| 179 | |
| 180 private: | |
| 181 // Overridden from Unsafe: | |
| 182 virtual void UnsafeMethod() override { | |
| 183 validator_->Call("UnsafeMethod", service_url_, remote_url_); | |
| 184 } | |
| 185 | |
| 186 CallValidator* validator_; | |
| 187 std::string service_url_; | |
| 188 std::string remote_url_; | |
| 189 StrongBinding<Unsafe> binding_; | |
| 190 | |
| 191 DISALLOW_COPY_AND_ASSIGN(UnsafeImpl); | |
| 192 }; | |
| 193 | |
| 194 // This class models a system service that exposes two interfaces, Safe and | |
| 195 // Unsafe. The interface Unsafe is not to be exposed to untrusted applications. | |
| 196 class ServiceApplication : public ApplicationDelegate, | |
| 197 public ApplicationLoader, | |
| 198 public InterfaceFactory<Safe>, | |
| 199 public InterfaceFactory<Unsafe> { | |
| 200 public: | |
| 201 explicit ServiceApplication(CallValidator* validator) | |
| 202 : validator_(validator) {} | |
| 203 ~ServiceApplication() override {} | |
| 204 | |
| 205 private: | |
| 206 // Overridden from ApplicationDelegate: | |
| 207 bool ConfigureIncomingConnection(ApplicationConnection* connection) override { | |
| 208 connection->AddService<Safe>(this); | |
| 209 connection->AddService<Unsafe>(this); | |
| 210 return true; | |
| 211 } | |
| 212 | |
| 213 // Overridden from ApplicationLoader: | |
| 214 void Load(const GURL& url, | |
| 215 InterfaceRequest<Application> application_request) override { | |
| 216 app_.reset(new ApplicationImpl(this, application_request.Pass())); | |
| 217 } | |
| 218 | |
| 219 // Overridden from InterfaceFactory<Safe>: | |
| 220 void Create(ApplicationConnection* connection, | |
| 221 InterfaceRequest<Safe> request) override { | |
| 222 new SafeImpl(validator_, app_->url(), connection->GetRemoteApplicationURL(), | |
| 223 request.Pass()); | |
| 224 } | |
| 225 | |
| 226 // Overridden from InterfaceFactory<Unsafe>: | |
| 227 void Create(ApplicationConnection* connection, | |
| 228 InterfaceRequest<Unsafe> request) override { | |
| 229 new UnsafeImpl(validator_, app_->url(), | |
| 230 connection->GetRemoteApplicationURL(), request.Pass()); | |
| 231 } | |
| 232 | |
| 233 scoped_ptr<ApplicationImpl> app_; | |
| 234 CallValidator* validator_; | |
| 235 | |
| 236 DISALLOW_COPY_AND_ASSIGN(ServiceApplication); | |
| 237 }; | |
| 238 | |
| 239 class TestApplicationManagerDelegate : public ApplicationManager::Delegate { | |
| 240 public: | |
| 241 TestApplicationManagerDelegate() {} | |
| 242 ~TestApplicationManagerDelegate() override {} | |
| 243 | |
| 244 private: | |
| 245 // Overridden from ApplicationManager::Delegate: | |
| 246 GURL ResolveMappings(const GURL& url) override { | |
| 247 return url; | |
| 248 } | |
| 249 GURL ResolveMojoURL(const GURL& url) override { | |
| 250 return url; | |
| 251 } | |
| 252 bool CreateFetcher(const GURL& url, | |
| 253 const Fetcher::FetchCallback& loader_callback) override { | |
| 254 return false; | |
| 255 } | |
| 256 | |
| 257 DISALLOW_COPY_AND_ASSIGN(TestApplicationManagerDelegate); | |
| 258 }; | |
| 259 | |
| 260 class CapabilityFilterTest : public testing::Test { | |
| 261 public: | |
| 262 CapabilityFilterTest() {} | |
| 263 ~CapabilityFilterTest() override {} | |
| 264 | |
| 265 protected: | |
| 266 void RunDriver(const std::string& url, CapabilityFilterPtr filter) { | |
| 267 ServiceProviderPtr services; | |
| 268 URLRequestPtr request(URLRequest::New()); | |
| 269 request->url = String::From(url); | |
| 270 application_manager_->ConnectToApplication( | |
| 271 NULL, request.Pass(), std::string(), GURL(), GetProxy(&services), | |
| 272 nullptr, filter.Pass(), base::MessageLoop::QuitWhenIdleClosure()); | |
| 273 DriverPtr driver; | |
| 274 ConnectToService(services.get(), &driver); | |
| 275 driver->Run(); | |
| 276 } | |
| 277 | |
| 278 base::MessageLoop* loop() { return &loop_; } | |
| 279 ApplicationManager* application_manager() { | |
| 280 return application_manager_.get(); | |
| 281 } | |
| 282 | |
| 283 private: | |
| 284 // Overridden from testing::Test: | |
| 285 void SetUp() override { | |
| 286 application_manager_.reset(new ApplicationManager(&test_delegate_)); | |
| 287 } | |
| 288 void TearDown() override { | |
| 289 application_manager_.reset(); | |
| 290 } | |
| 291 | |
| 292 base::ShadowingAtExitManager at_exit_; | |
| 293 TestApplicationManagerDelegate test_delegate_; | |
| 294 base::MessageLoop loop_; | |
| 295 scoped_ptr<ApplicationManager> application_manager_; | |
| 296 | |
| 297 DISALLOW_COPY_AND_ASSIGN(CapabilityFilterTest); | |
| 298 }; | |
| 299 | |
| 300 TEST_F(CapabilityFilterTest, RestrictedInterfaces) { | |
| 301 std::set<std::string> valid_calls; | |
| 302 valid_calls.insert("SafeMethod test:service test:untrusted_application"); | |
| 303 valid_calls.insert("SafeMethod test:service test:trusted_application"); | |
| 304 valid_calls.insert("UnsafeMethod test:service test:trusted_application"); | |
| 305 std::set<std::string> invalid_calls; | |
| 306 invalid_calls.insert("UnsafeMethod test:service test:untrusted_application"); | |
| 307 CallValidator validator(loop(), valid_calls, invalid_calls); | |
| 308 application_manager()->SetLoaderForURL( | |
| 309 make_scoped_ptr(new TestApplication(false)), | |
| 310 GURL("test:trusted_application")); | |
| 311 application_manager()->SetLoaderForURL( | |
| 312 make_scoped_ptr(new TestApplication(false)), | |
| 313 GURL("test:untrusted_application")); | |
| 314 application_manager()->SetLoaderForURL( | |
| 315 make_scoped_ptr(new ServiceApplication(&validator)), | |
| 316 GURL("test:service")); | |
| 317 | |
| 318 Array<String> interfaces(Array<String>::New(1)); | |
| 319 interfaces[0] = String::From(std::string(Safe::Name_)); | |
| 320 CapabilityFilterPtr filter(CapabilityFilter::New()); | |
| 321 filter->filter.insert("test:service", interfaces.Pass()); | |
| 322 | |
| 323 // This first instance is restricted and will only be able to call the safe | |
| 324 // method. | |
| 325 RunDriver("test:untrusted_application", filter.Pass()); | |
| 326 | |
| 327 // This instance of the application should see both method calls. | |
| 328 RunDriver("test:trusted_application", nullptr); | |
| 329 | |
| 330 loop()->Run(); | |
| 331 | |
| 332 EXPECT_TRUE(validator.called_all_valid()); | |
| 333 } | |
| 334 | |
| 335 TEST_F(CapabilityFilterTest, RestrictedApplications) { | |
| 336 std::set<std::string> valid_calls; | |
| 337 valid_calls.insert("SafeMethod test:service test:trusted_application"); | |
| 338 valid_calls.insert("SafeMethod test:service test:untrusted_application"); | |
| 339 valid_calls.insert("SafeMethod test:service2 test:trusted_application"); | |
| 340 valid_calls.insert("UnsafeMethod test:service test:trusted_application"); | |
| 341 valid_calls.insert("UnsafeMethod test:service2 test:trusted_application"); | |
| 342 | |
| 343 std::set<std::string> invalid_calls; | |
| 344 invalid_calls.insert("SafeMethod test:service2 test:untrusted_application"); | |
| 345 invalid_calls.insert("UnsafeMethod test:service test:untrusted_application"); | |
| 346 invalid_calls.insert("UnsafeMethod test:service2 test:untrusted_application"); | |
| 347 | |
| 348 CallValidator validator(loop(), valid_calls, invalid_calls); | |
| 349 application_manager()->SetLoaderForURL( | |
| 350 make_scoped_ptr(new TestApplication(true)), | |
| 351 GURL("test:trusted_application")); | |
| 352 application_manager()->SetLoaderForURL( | |
| 353 make_scoped_ptr(new TestApplication(true)), | |
| 354 GURL("test:untrusted_application")); | |
| 355 application_manager()->SetLoaderForURL( | |
| 356 make_scoped_ptr(new ServiceApplication(&validator)), | |
| 357 GURL("test:service")); | |
| 358 application_manager()->SetLoaderForURL( | |
| 359 make_scoped_ptr(new ServiceApplication(&validator)), | |
| 360 GURL("test:service2")); | |
| 361 | |
| 362 Array<String> interfaces(Array<String>::New(1)); | |
| 363 interfaces[0] = String::From(std::string(Safe::Name_)); | |
| 364 CapabilityFilterPtr filter(CapabilityFilter::New()); | |
| 365 filter->filter.insert("test:service", interfaces.Pass()); | |
| 366 | |
| 367 // This first instance is restricted and will only be able to call the safe | |
| 368 // method. | |
| 369 RunDriver("test:untrusted_application", filter.Pass()); | |
| 370 | |
| 371 // This instance of the application should see both method calls. | |
| 372 RunDriver("test:trusted_application", nullptr); | |
| 373 | |
| 374 loop()->Run(); | |
| 375 | |
| 376 EXPECT_TRUE(validator.called_all_valid()); | |
| 377 } | |
| 378 | |
| 379 } // namespace | |
| 380 } // namespace shell | |
| 381 } // namespace mojo | |
| OLD | NEW |