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