OLD | NEW |
| (Empty) |
1 // Copyright 2014 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 "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 "mojo/public/cpp/application/application_connection.h" | |
11 #include "mojo/public/cpp/application/application_delegate.h" | |
12 #include "mojo/public/cpp/application/application_impl.h" | |
13 #include "mojo/public/cpp/application/interface_factory.h" | |
14 #include "mojo/public/cpp/bindings/strong_binding.h" | |
15 #include "mojo/public/interfaces/application/service_provider.mojom.h" | |
16 #include "mojo/shell/application_manager/application_loader.h" | |
17 #include "mojo/shell/application_manager/application_manager.h" | |
18 #include "mojo/shell/application_manager/test.mojom.h" | |
19 #include "testing/gtest/include/gtest/gtest.h" | |
20 | |
21 namespace mojo { | |
22 namespace shell { | |
23 namespace { | |
24 | |
25 const char kTestURLString[] = "test:testService"; | |
26 const char kTestAURLString[] = "test:TestA"; | |
27 const char kTestBURLString[] = "test:TestB"; | |
28 | |
29 struct TestContext { | |
30 TestContext() : num_impls(0), num_loader_deletes(0) {} | |
31 std::string last_test_string; | |
32 int num_impls; | |
33 int num_loader_deletes; | |
34 }; | |
35 | |
36 void QuitClosure(bool* value) { | |
37 *value = true; | |
38 base::MessageLoop::current()->QuitWhenIdle(); | |
39 } | |
40 | |
41 class QuitMessageLoopErrorHandler : public ErrorHandler { | |
42 public: | |
43 QuitMessageLoopErrorHandler() {} | |
44 ~QuitMessageLoopErrorHandler() override {} | |
45 | |
46 // |ErrorHandler| implementation: | |
47 void OnConnectionError() override { | |
48 base::MessageLoop::current()->QuitWhenIdle(); | |
49 } | |
50 | |
51 private: | |
52 DISALLOW_COPY_AND_ASSIGN(QuitMessageLoopErrorHandler); | |
53 }; | |
54 | |
55 class TestServiceImpl : public TestService { | |
56 public: | |
57 TestServiceImpl(TestContext* context, InterfaceRequest<TestService> request) | |
58 : context_(context), binding_(this, request.Pass()) { | |
59 ++context_->num_impls; | |
60 } | |
61 | |
62 ~TestServiceImpl() override { | |
63 --context_->num_impls; | |
64 if (!base::MessageLoop::current()->is_running()) | |
65 return; | |
66 base::MessageLoop::current()->Quit(); | |
67 } | |
68 | |
69 // TestService implementation: | |
70 void Test(const String& test_string, | |
71 const Callback<void()>& callback) override { | |
72 context_->last_test_string = test_string; | |
73 callback.Run(); | |
74 } | |
75 | |
76 private: | |
77 TestContext* context_; | |
78 StrongBinding<TestService> binding_; | |
79 }; | |
80 | |
81 class TestClient { | |
82 public: | |
83 explicit TestClient(TestServicePtr service) | |
84 : service_(service.Pass()), quit_after_ack_(false) {} | |
85 | |
86 void AckTest() { | |
87 if (quit_after_ack_) | |
88 base::MessageLoop::current()->Quit(); | |
89 } | |
90 | |
91 void Test(const std::string& test_string) { | |
92 quit_after_ack_ = true; | |
93 service_->Test(test_string, | |
94 base::Bind(&TestClient::AckTest, base::Unretained(this))); | |
95 } | |
96 | |
97 private: | |
98 TestServicePtr service_; | |
99 bool quit_after_ack_; | |
100 DISALLOW_COPY_AND_ASSIGN(TestClient); | |
101 }; | |
102 | |
103 class TestApplicationLoader : public ApplicationLoader, | |
104 public ApplicationDelegate, | |
105 public InterfaceFactory<TestService> { | |
106 public: | |
107 TestApplicationLoader() : context_(nullptr), num_loads_(0) {} | |
108 | |
109 ~TestApplicationLoader() override { | |
110 if (context_) | |
111 ++context_->num_loader_deletes; | |
112 test_app_.reset(); | |
113 } | |
114 | |
115 void set_context(TestContext* context) { context_ = context; } | |
116 int num_loads() const { return num_loads_; } | |
117 const std::vector<std::string>& GetArgs() const { return test_app_->args(); } | |
118 | |
119 private: | |
120 // ApplicationLoader implementation. | |
121 void Load(const GURL& url, | |
122 InterfaceRequest<Application> application_request) override { | |
123 ++num_loads_; | |
124 test_app_.reset(new ApplicationImpl(this, application_request.Pass())); | |
125 } | |
126 | |
127 // ApplicationDelegate implementation. | |
128 bool ConfigureIncomingConnection(ApplicationConnection* connection) override { | |
129 connection->AddService(this); | |
130 return true; | |
131 } | |
132 | |
133 // InterfaceFactory implementation. | |
134 void Create(ApplicationConnection* connection, | |
135 InterfaceRequest<TestService> request) override { | |
136 new TestServiceImpl(context_, request.Pass()); | |
137 } | |
138 | |
139 scoped_ptr<ApplicationImpl> test_app_; | |
140 TestContext* context_; | |
141 int num_loads_; | |
142 DISALLOW_COPY_AND_ASSIGN(TestApplicationLoader); | |
143 }; | |
144 | |
145 class ClosingApplicationLoader : public ApplicationLoader { | |
146 private: | |
147 // ApplicationLoader implementation. | |
148 void Load(const GURL& url, | |
149 InterfaceRequest<Application> application_request) override {} | |
150 }; | |
151 | |
152 class TesterContext { | |
153 public: | |
154 explicit TesterContext(base::MessageLoop* loop) | |
155 : num_b_calls_(0), | |
156 num_c_calls_(0), | |
157 num_a_deletes_(0), | |
158 num_b_deletes_(0), | |
159 num_c_deletes_(0), | |
160 tester_called_quit_(false), | |
161 a_called_quit_(false), | |
162 loop_(loop) {} | |
163 | |
164 void IncrementNumBCalls() { | |
165 base::AutoLock lock(lock_); | |
166 num_b_calls_++; | |
167 } | |
168 | |
169 void IncrementNumCCalls() { | |
170 base::AutoLock lock(lock_); | |
171 num_c_calls_++; | |
172 } | |
173 | |
174 void IncrementNumADeletes() { | |
175 base::AutoLock lock(lock_); | |
176 num_a_deletes_++; | |
177 } | |
178 | |
179 void IncrementNumBDeletes() { | |
180 base::AutoLock lock(lock_); | |
181 num_b_deletes_++; | |
182 } | |
183 | |
184 void IncrementNumCDeletes() { | |
185 base::AutoLock lock(lock_); | |
186 num_c_deletes_++; | |
187 } | |
188 | |
189 void set_tester_called_quit() { | |
190 base::AutoLock lock(lock_); | |
191 tester_called_quit_ = true; | |
192 } | |
193 | |
194 void set_a_called_quit() { | |
195 base::AutoLock lock(lock_); | |
196 a_called_quit_ = true; | |
197 } | |
198 | |
199 int num_b_calls() { | |
200 base::AutoLock lock(lock_); | |
201 return num_b_calls_; | |
202 } | |
203 int num_c_calls() { | |
204 base::AutoLock lock(lock_); | |
205 return num_c_calls_; | |
206 } | |
207 int num_a_deletes() { | |
208 base::AutoLock lock(lock_); | |
209 return num_a_deletes_; | |
210 } | |
211 int num_b_deletes() { | |
212 base::AutoLock lock(lock_); | |
213 return num_b_deletes_; | |
214 } | |
215 int num_c_deletes() { | |
216 base::AutoLock lock(lock_); | |
217 return num_c_deletes_; | |
218 } | |
219 bool tester_called_quit() { | |
220 base::AutoLock lock(lock_); | |
221 return tester_called_quit_; | |
222 } | |
223 bool a_called_quit() { | |
224 base::AutoLock lock(lock_); | |
225 return a_called_quit_; | |
226 } | |
227 | |
228 void QuitSoon() { | |
229 loop_->PostTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure()); | |
230 } | |
231 | |
232 private: | |
233 // lock_ protects all members except for loop_ which must be unchanged for the | |
234 // lifetime of this class. | |
235 base::Lock lock_; | |
236 int num_b_calls_; | |
237 int num_c_calls_; | |
238 int num_a_deletes_; | |
239 int num_b_deletes_; | |
240 int num_c_deletes_; | |
241 bool tester_called_quit_; | |
242 bool a_called_quit_; | |
243 | |
244 base::MessageLoop* loop_; | |
245 }; | |
246 | |
247 // Used to test that the requestor url will be correctly passed. | |
248 class TestAImpl : public TestA { | |
249 public: | |
250 TestAImpl(ApplicationImpl* app_impl, | |
251 TesterContext* test_context, | |
252 InterfaceRequest<TestA> request) | |
253 : test_context_(test_context), binding_(this, request.Pass()) { | |
254 app_impl->ConnectToApplication(kTestBURLString)->ConnectToService(&b_); | |
255 } | |
256 | |
257 ~TestAImpl() override { | |
258 test_context_->IncrementNumADeletes(); | |
259 if (base::MessageLoop::current()->is_running()) | |
260 Quit(); | |
261 } | |
262 | |
263 private: | |
264 void CallB() override { | |
265 b_->B(base::Bind(&TestAImpl::Quit, base::Unretained(this))); | |
266 } | |
267 | |
268 void CallCFromB() override { | |
269 b_->CallC(base::Bind(&TestAImpl::Quit, base::Unretained(this))); | |
270 } | |
271 | |
272 void Quit() { | |
273 base::MessageLoop::current()->Quit(); | |
274 test_context_->set_a_called_quit(); | |
275 test_context_->QuitSoon(); | |
276 } | |
277 | |
278 TesterContext* test_context_; | |
279 TestBPtr b_; | |
280 StrongBinding<TestA> binding_; | |
281 }; | |
282 | |
283 class TestBImpl : public TestB { | |
284 public: | |
285 TestBImpl(ApplicationConnection* connection, | |
286 TesterContext* test_context, | |
287 InterfaceRequest<TestB> request) | |
288 : test_context_(test_context), binding_(this, request.Pass()) { | |
289 connection->ConnectToService(&c_); | |
290 } | |
291 | |
292 ~TestBImpl() override { | |
293 test_context_->IncrementNumBDeletes(); | |
294 if (base::MessageLoop::current()->is_running()) | |
295 base::MessageLoop::current()->Quit(); | |
296 test_context_->QuitSoon(); | |
297 } | |
298 | |
299 private: | |
300 void B(const Callback<void()>& callback) override { | |
301 test_context_->IncrementNumBCalls(); | |
302 callback.Run(); | |
303 } | |
304 | |
305 void CallC(const Callback<void()>& callback) override { | |
306 test_context_->IncrementNumBCalls(); | |
307 c_->C(callback); | |
308 } | |
309 | |
310 TesterContext* test_context_; | |
311 TestCPtr c_; | |
312 StrongBinding<TestB> binding_; | |
313 }; | |
314 | |
315 class TestCImpl : public TestC { | |
316 public: | |
317 TestCImpl(ApplicationConnection* connection, | |
318 TesterContext* test_context, | |
319 InterfaceRequest<TestC> request) | |
320 : test_context_(test_context), binding_(this, request.Pass()) {} | |
321 | |
322 ~TestCImpl() override { test_context_->IncrementNumCDeletes(); } | |
323 | |
324 private: | |
325 void C(const Callback<void()>& callback) override { | |
326 test_context_->IncrementNumCCalls(); | |
327 callback.Run(); | |
328 } | |
329 | |
330 TesterContext* test_context_; | |
331 StrongBinding<TestC> binding_; | |
332 }; | |
333 | |
334 class Tester : public ApplicationDelegate, | |
335 public ApplicationLoader, | |
336 public InterfaceFactory<TestA>, | |
337 public InterfaceFactory<TestB>, | |
338 public InterfaceFactory<TestC> { | |
339 public: | |
340 Tester(TesterContext* context, const std::string& requestor_url) | |
341 : context_(context), requestor_url_(requestor_url) {} | |
342 ~Tester() override {} | |
343 | |
344 private: | |
345 void Load(const GURL& url, | |
346 InterfaceRequest<Application> application_request) override { | |
347 app_.reset(new ApplicationImpl(this, application_request.Pass())); | |
348 } | |
349 | |
350 bool ConfigureIncomingConnection(ApplicationConnection* connection) override { | |
351 if (!requestor_url_.empty() && | |
352 requestor_url_ != connection->GetRemoteApplicationURL()) { | |
353 context_->set_tester_called_quit(); | |
354 context_->QuitSoon(); | |
355 base::MessageLoop::current()->Quit(); | |
356 return false; | |
357 } | |
358 // If we're coming from A, then add B, otherwise A. | |
359 if (connection->GetRemoteApplicationURL() == kTestAURLString) | |
360 connection->AddService<TestB>(this); | |
361 else | |
362 connection->AddService<TestA>(this); | |
363 return true; | |
364 } | |
365 | |
366 bool ConfigureOutgoingConnection(ApplicationConnection* connection) override { | |
367 // If we're connecting to B, then add C. | |
368 if (connection->GetRemoteApplicationURL() == kTestBURLString) | |
369 connection->AddService<TestC>(this); | |
370 return true; | |
371 } | |
372 | |
373 void Create(ApplicationConnection* connection, | |
374 InterfaceRequest<TestA> request) override { | |
375 a_bindings_.push_back(new TestAImpl(app_.get(), context_, request.Pass())); | |
376 } | |
377 | |
378 void Create(ApplicationConnection* connection, | |
379 InterfaceRequest<TestB> request) override { | |
380 new TestBImpl(connection, context_, request.Pass()); | |
381 } | |
382 | |
383 void Create(ApplicationConnection* connection, | |
384 InterfaceRequest<TestC> request) override { | |
385 new TestCImpl(connection, context_, request.Pass()); | |
386 } | |
387 | |
388 TesterContext* context_; | |
389 scoped_ptr<ApplicationImpl> app_; | |
390 std::string requestor_url_; | |
391 ScopedVector<TestAImpl> a_bindings_; | |
392 }; | |
393 | |
394 class TestDelegate : public ApplicationManager::Delegate { | |
395 public: | |
396 void AddMapping(const GURL& from, const GURL& to) { mappings_[from] = to; } | |
397 | |
398 // ApplicationManager::Delegate | |
399 GURL ResolveMappings(const GURL& url) override { | |
400 auto it = mappings_.find(url); | |
401 if (it != mappings_.end()) | |
402 return it->second; | |
403 return url; | |
404 } | |
405 GURL ResolveMojoURL(const GURL& url) override { | |
406 GURL mapped_url = ResolveMappings(url); | |
407 // The shell automatically map mojo URLs. | |
408 if (mapped_url.scheme() == "mojo") { | |
409 url::Replacements<char> replacements; | |
410 replacements.SetScheme("file", url::Component(0, 4)); | |
411 mapped_url = mapped_url.ReplaceComponents(replacements); | |
412 } | |
413 return mapped_url; | |
414 } | |
415 | |
416 private: | |
417 std::map<GURL, GURL> mappings_; | |
418 }; | |
419 | |
420 class ApplicationManagerTest : public testing::Test { | |
421 public: | |
422 ApplicationManagerTest() : tester_context_(&loop_) {} | |
423 | |
424 ~ApplicationManagerTest() override {} | |
425 | |
426 void SetUp() override { | |
427 application_manager_.reset(new ApplicationManager(&test_delegate_)); | |
428 test_loader_ = new TestApplicationLoader; | |
429 test_loader_->set_context(&context_); | |
430 application_manager_->set_default_loader( | |
431 scoped_ptr<ApplicationLoader>(test_loader_)); | |
432 | |
433 TestServicePtr service_proxy; | |
434 application_manager_->ConnectToService(GURL(kTestURLString), | |
435 &service_proxy); | |
436 test_client_.reset(new TestClient(service_proxy.Pass())); | |
437 } | |
438 | |
439 void TearDown() override { | |
440 test_client_.reset(); | |
441 application_manager_.reset(); | |
442 } | |
443 | |
444 void AddLoaderForURL(const GURL& url, const std::string& requestor_url) { | |
445 application_manager_->SetLoaderForURL( | |
446 make_scoped_ptr(new Tester(&tester_context_, requestor_url)), url); | |
447 } | |
448 | |
449 bool HasFactoryForTestURL() { | |
450 ApplicationManager::TestAPI manager_test_api(application_manager_.get()); | |
451 return manager_test_api.HasFactoryForURL(GURL(kTestURLString)); | |
452 } | |
453 | |
454 protected: | |
455 base::ShadowingAtExitManager at_exit_; | |
456 TestDelegate test_delegate_; | |
457 TestApplicationLoader* test_loader_; | |
458 TesterContext tester_context_; | |
459 TestContext context_; | |
460 base::MessageLoop loop_; | |
461 scoped_ptr<TestClient> test_client_; | |
462 scoped_ptr<ApplicationManager> application_manager_; | |
463 DISALLOW_COPY_AND_ASSIGN(ApplicationManagerTest); | |
464 }; | |
465 | |
466 TEST_F(ApplicationManagerTest, Basic) { | |
467 test_client_->Test("test"); | |
468 loop_.Run(); | |
469 EXPECT_EQ(std::string("test"), context_.last_test_string); | |
470 } | |
471 | |
472 // Confirm that no arguments are sent to an application by default. | |
473 TEST_F(ApplicationManagerTest, NoArgs) { | |
474 ApplicationManager am(&test_delegate_); | |
475 GURL test_url("test:test"); | |
476 TestApplicationLoader* loader = new TestApplicationLoader; | |
477 loader->set_context(&context_); | |
478 am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(loader), test_url); | |
479 TestServicePtr test_service; | |
480 am.ConnectToService(test_url, &test_service); | |
481 TestClient test_client(test_service.Pass()); | |
482 test_client.Test("test"); | |
483 loop_.Run(); | |
484 std::vector<std::string> app_args = loader->GetArgs(); | |
485 EXPECT_EQ(0U, app_args.size()); | |
486 } | |
487 | |
488 // Confirm that url mappings are respected. | |
489 TEST_F(ApplicationManagerTest, URLMapping) { | |
490 ApplicationManager am(&test_delegate_); | |
491 GURL test_url("test:test"); | |
492 GURL test_url2("test:test2"); | |
493 test_delegate_.AddMapping(test_url, test_url2); | |
494 TestApplicationLoader* loader = new TestApplicationLoader; | |
495 loader->set_context(&context_); | |
496 am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(loader), test_url2); | |
497 { | |
498 // Connext to the mapped url | |
499 TestServicePtr test_service; | |
500 am.ConnectToService(test_url, &test_service); | |
501 TestClient test_client(test_service.Pass()); | |
502 test_client.Test("test"); | |
503 loop_.Run(); | |
504 } | |
505 { | |
506 // Connext to the target url | |
507 TestServicePtr test_service; | |
508 am.ConnectToService(test_url2, &test_service); | |
509 TestClient test_client(test_service.Pass()); | |
510 test_client.Test("test"); | |
511 loop_.Run(); | |
512 } | |
513 } | |
514 | |
515 TEST_F(ApplicationManagerTest, ClientError) { | |
516 test_client_->Test("test"); | |
517 EXPECT_TRUE(HasFactoryForTestURL()); | |
518 loop_.Run(); | |
519 EXPECT_EQ(1, context_.num_impls); | |
520 test_client_.reset(); | |
521 loop_.Run(); | |
522 EXPECT_EQ(0, context_.num_impls); | |
523 EXPECT_TRUE(HasFactoryForTestURL()); | |
524 } | |
525 | |
526 TEST_F(ApplicationManagerTest, Deletes) { | |
527 { | |
528 ApplicationManager am(&test_delegate_); | |
529 TestApplicationLoader* default_loader = new TestApplicationLoader; | |
530 default_loader->set_context(&context_); | |
531 TestApplicationLoader* url_loader1 = new TestApplicationLoader; | |
532 TestApplicationLoader* url_loader2 = new TestApplicationLoader; | |
533 url_loader1->set_context(&context_); | |
534 url_loader2->set_context(&context_); | |
535 TestApplicationLoader* scheme_loader1 = new TestApplicationLoader; | |
536 TestApplicationLoader* scheme_loader2 = new TestApplicationLoader; | |
537 scheme_loader1->set_context(&context_); | |
538 scheme_loader2->set_context(&context_); | |
539 am.set_default_loader(scoped_ptr<ApplicationLoader>(default_loader)); | |
540 am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(url_loader1), | |
541 GURL("test:test1")); | |
542 am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(url_loader2), | |
543 GURL("test:test1")); | |
544 am.SetLoaderForScheme(scoped_ptr<ApplicationLoader>(scheme_loader1), | |
545 "test"); | |
546 am.SetLoaderForScheme(scoped_ptr<ApplicationLoader>(scheme_loader2), | |
547 "test"); | |
548 } | |
549 EXPECT_EQ(5, context_.num_loader_deletes); | |
550 } | |
551 | |
552 // Confirm that both urls and schemes can have their loaders explicitly set. | |
553 TEST_F(ApplicationManagerTest, SetLoaders) { | |
554 TestApplicationLoader* default_loader = new TestApplicationLoader; | |
555 TestApplicationLoader* url_loader = new TestApplicationLoader; | |
556 TestApplicationLoader* scheme_loader = new TestApplicationLoader; | |
557 application_manager_->set_default_loader( | |
558 scoped_ptr<ApplicationLoader>(default_loader)); | |
559 application_manager_->SetLoaderForURL( | |
560 scoped_ptr<ApplicationLoader>(url_loader), GURL("test:test1")); | |
561 application_manager_->SetLoaderForScheme( | |
562 scoped_ptr<ApplicationLoader>(scheme_loader), "test"); | |
563 | |
564 // test::test1 should go to url_loader. | |
565 TestServicePtr test_service; | |
566 application_manager_->ConnectToService(GURL("test:test1"), &test_service); | |
567 EXPECT_EQ(1, url_loader->num_loads()); | |
568 EXPECT_EQ(0, scheme_loader->num_loads()); | |
569 EXPECT_EQ(0, default_loader->num_loads()); | |
570 | |
571 // test::test2 should go to scheme loader. | |
572 application_manager_->ConnectToService(GURL("test:test2"), &test_service); | |
573 EXPECT_EQ(1, url_loader->num_loads()); | |
574 EXPECT_EQ(1, scheme_loader->num_loads()); | |
575 EXPECT_EQ(0, default_loader->num_loads()); | |
576 | |
577 // http::test1 should go to default loader. | |
578 application_manager_->ConnectToService(GURL("http:test1"), &test_service); | |
579 EXPECT_EQ(1, url_loader->num_loads()); | |
580 EXPECT_EQ(1, scheme_loader->num_loads()); | |
581 EXPECT_EQ(1, default_loader->num_loads()); | |
582 } | |
583 | |
584 // Confirm that the url of a service is correctly passed to another service that | |
585 // it loads. | |
586 TEST_F(ApplicationManagerTest, ACallB) { | |
587 // Any url can load a. | |
588 AddLoaderForURL(GURL(kTestAURLString), std::string()); | |
589 | |
590 // Only a can load b. | |
591 AddLoaderForURL(GURL(kTestBURLString), kTestAURLString); | |
592 | |
593 TestAPtr a; | |
594 application_manager_->ConnectToService(GURL(kTestAURLString), &a); | |
595 a->CallB(); | |
596 loop_.Run(); | |
597 EXPECT_EQ(1, tester_context_.num_b_calls()); | |
598 EXPECT_TRUE(tester_context_.a_called_quit()); | |
599 } | |
600 | |
601 // A calls B which calls C. | |
602 TEST_F(ApplicationManagerTest, BCallC) { | |
603 // Any url can load a. | |
604 AddLoaderForURL(GURL(kTestAURLString), std::string()); | |
605 | |
606 // Only a can load b. | |
607 AddLoaderForURL(GURL(kTestBURLString), kTestAURLString); | |
608 | |
609 TestAPtr a; | |
610 application_manager_->ConnectToService(GURL(kTestAURLString), &a); | |
611 a->CallCFromB(); | |
612 loop_.Run(); | |
613 | |
614 EXPECT_EQ(1, tester_context_.num_b_calls()); | |
615 EXPECT_EQ(1, tester_context_.num_c_calls()); | |
616 EXPECT_TRUE(tester_context_.a_called_quit()); | |
617 } | |
618 | |
619 // Confirm that a service impl will be deleted if the app that connected to | |
620 // it goes away. | |
621 TEST_F(ApplicationManagerTest, BDeleted) { | |
622 AddLoaderForURL(GURL(kTestAURLString), std::string()); | |
623 AddLoaderForURL(GURL(kTestBURLString), std::string()); | |
624 | |
625 TestAPtr a; | |
626 application_manager_->ConnectToService(GURL(kTestAURLString), &a); | |
627 | |
628 a->CallB(); | |
629 loop_.Run(); | |
630 | |
631 // Kills the a app. | |
632 application_manager_->SetLoaderForURL(scoped_ptr<ApplicationLoader>(), | |
633 GURL(kTestAURLString)); | |
634 loop_.Run(); | |
635 | |
636 EXPECT_EQ(1, tester_context_.num_b_deletes()); | |
637 } | |
638 | |
639 // Confirm that the url of a service is correctly passed to another service that | |
640 // it loads, and that it can be rejected. | |
641 TEST_F(ApplicationManagerTest, ANoLoadB) { | |
642 // Any url can load a. | |
643 AddLoaderForURL(GURL(kTestAURLString), std::string()); | |
644 | |
645 // Only c can load b, so this will fail. | |
646 AddLoaderForURL(GURL(kTestBURLString), "test:TestC"); | |
647 | |
648 TestAPtr a; | |
649 application_manager_->ConnectToService(GURL(kTestAURLString), &a); | |
650 a->CallB(); | |
651 loop_.Run(); | |
652 EXPECT_EQ(0, tester_context_.num_b_calls()); | |
653 | |
654 EXPECT_FALSE(tester_context_.a_called_quit()); | |
655 EXPECT_TRUE(tester_context_.tester_called_quit()); | |
656 } | |
657 | |
658 TEST_F(ApplicationManagerTest, NoServiceNoLoad) { | |
659 AddLoaderForURL(GURL(kTestAURLString), std::string()); | |
660 | |
661 // There is no TestC service implementation registered with | |
662 // ApplicationManager, so this cannot succeed (but also shouldn't crash). | |
663 TestCPtr c; | |
664 application_manager_->ConnectToService(GURL(kTestAURLString), &c); | |
665 QuitMessageLoopErrorHandler quitter; | |
666 c.set_error_handler(&quitter); | |
667 | |
668 loop_.Run(); | |
669 EXPECT_TRUE(c.encountered_error()); | |
670 } | |
671 | |
672 TEST_F(ApplicationManagerTest, MappedURLsShouldNotCauseDuplicateLoad) { | |
673 test_delegate_.AddMapping(GURL("foo:foo2"), GURL("foo:foo")); | |
674 // 1 because ApplicationManagerTest connects once at startup. | |
675 EXPECT_EQ(1, test_loader_->num_loads()); | |
676 | |
677 TestServicePtr test_service; | |
678 application_manager_->ConnectToService(GURL("foo:foo"), &test_service); | |
679 EXPECT_EQ(2, test_loader_->num_loads()); | |
680 | |
681 TestServicePtr test_service2; | |
682 application_manager_->ConnectToService(GURL("foo:foo2"), &test_service2); | |
683 EXPECT_EQ(2, test_loader_->num_loads()); | |
684 | |
685 TestServicePtr test_service3; | |
686 application_manager_->ConnectToService(GURL("bar:bar"), &test_service2); | |
687 EXPECT_EQ(3, test_loader_->num_loads()); | |
688 } | |
689 | |
690 TEST_F(ApplicationManagerTest, MappedURLsShouldWorkWithLoaders) { | |
691 TestApplicationLoader* custom_loader = new TestApplicationLoader; | |
692 TestContext context; | |
693 custom_loader->set_context(&context); | |
694 application_manager_->SetLoaderForURL(make_scoped_ptr(custom_loader), | |
695 GURL("mojo:foo")); | |
696 test_delegate_.AddMapping(GURL("mojo:foo2"), GURL("mojo:foo")); | |
697 | |
698 TestServicePtr test_service; | |
699 application_manager_->ConnectToService(GURL("mojo:foo2"), &test_service); | |
700 EXPECT_EQ(1, custom_loader->num_loads()); | |
701 custom_loader->set_context(nullptr); | |
702 } | |
703 | |
704 TEST_F(ApplicationManagerTest, TestQueryWithLoaders) { | |
705 TestApplicationLoader* url_loader = new TestApplicationLoader; | |
706 TestApplicationLoader* scheme_loader = new TestApplicationLoader; | |
707 application_manager_->SetLoaderForURL( | |
708 scoped_ptr<ApplicationLoader>(url_loader), GURL("test:test1")); | |
709 application_manager_->SetLoaderForScheme( | |
710 scoped_ptr<ApplicationLoader>(scheme_loader), "test"); | |
711 | |
712 // test::test1 should go to url_loader. | |
713 TestServicePtr test_service; | |
714 application_manager_->ConnectToService(GURL("test:test1?foo=bar"), | |
715 &test_service); | |
716 EXPECT_EQ(1, url_loader->num_loads()); | |
717 EXPECT_EQ(0, scheme_loader->num_loads()); | |
718 | |
719 // test::test2 should go to scheme loader. | |
720 application_manager_->ConnectToService(GURL("test:test2?foo=bar"), | |
721 &test_service); | |
722 EXPECT_EQ(1, url_loader->num_loads()); | |
723 EXPECT_EQ(1, scheme_loader->num_loads()); | |
724 } | |
725 | |
726 TEST_F(ApplicationManagerTest, TestEndApplicationClosure) { | |
727 ClosingApplicationLoader* loader = new ClosingApplicationLoader(); | |
728 application_manager_->SetLoaderForScheme( | |
729 scoped_ptr<ApplicationLoader>(loader), "test"); | |
730 | |
731 bool called = false; | |
732 application_manager_->ConnectToApplication( | |
733 GURL("test:test"), GURL(), nullptr, nullptr, | |
734 base::Bind(&QuitClosure, base::Unretained(&called))); | |
735 loop_.Run(); | |
736 EXPECT_TRUE(called); | |
737 } | |
738 | |
739 } // namespace | |
740 } // namespace shell | |
741 } // namespace mojo | |
OLD | NEW |