Roll src/third_party/WebKit d9c6159:8139f33 (svn 201974:201975)
[chromium-blink-merge.git] / mojo / shell / application_manager_unittest.cc
blob56d2fb5bbff54da65d2e2d214966c76324cdc89e
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.
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/run_loop.h"
11 #include "mojo/application/public/cpp/application_connection.h"
12 #include "mojo/application/public/cpp/application_delegate.h"
13 #include "mojo/application/public/cpp/application_impl.h"
14 #include "mojo/application/public/cpp/interface_factory.h"
15 #include "mojo/application/public/interfaces/content_handler.mojom.h"
16 #include "mojo/application/public/interfaces/service_provider.mojom.h"
17 #include "mojo/public/cpp/bindings/strong_binding.h"
18 #include "mojo/shell/application_loader.h"
19 #include "mojo/shell/application_manager.h"
20 #include "mojo/shell/fetcher.h"
21 #include "mojo/shell/test.mojom.h"
22 #include "testing/gtest/include/gtest/gtest.h"
24 namespace mojo {
25 namespace shell {
26 namespace {
28 const char kTestURLString[] = "test:testService";
29 const char kTestAURLString[] = "test:TestA";
30 const char kTestBURLString[] = "test:TestB";
32 const char kTestMimeType[] = "test/mime-type";
34 class TestMimeTypeFetcher : public Fetcher {
35 public:
36 TestMimeTypeFetcher(const FetchCallback& fetch_callback,
37 const GURL& url,
38 const std::string& mime_type)
39 : Fetcher(fetch_callback), url_(url), mime_type_(mime_type) {
40 loader_callback_.Run(make_scoped_ptr(this));
42 ~TestMimeTypeFetcher() override {}
44 // Fetcher:
45 const GURL& GetURL() const override { return url_; }
46 GURL GetRedirectURL() const override { return GURL("yyy"); }
47 GURL GetRedirectReferer() const override { return GURL(); }
48 URLResponsePtr AsURLResponse(base::TaskRunner* task_runner,
49 uint32_t skip) override {
50 return URLResponse::New().Pass();
52 void AsPath(
53 base::TaskRunner* task_runner,
54 base::Callback<void(const base::FilePath&, bool)> callback) override {}
55 std::string MimeType() override { return mime_type_; }
56 bool HasMojoMagic() override { return false; }
57 bool PeekFirstLine(std::string* line) override { return false; }
59 private:
60 const GURL url_;
61 const std::string mime_type_;
63 DISALLOW_COPY_AND_ASSIGN(TestMimeTypeFetcher);
66 struct TestContext {
67 TestContext() : num_impls(0), num_loader_deletes(0) {}
68 std::string last_test_string;
69 int num_impls;
70 int num_loader_deletes;
73 void QuitClosure(bool* value) {
74 *value = true;
75 base::MessageLoop::current()->QuitWhenIdle();
78 class TestServiceImpl : public TestService {
79 public:
80 TestServiceImpl(TestContext* context, InterfaceRequest<TestService> request)
81 : context_(context), binding_(this, request.Pass()) {
82 ++context_->num_impls;
85 ~TestServiceImpl() override {
86 --context_->num_impls;
87 if (!base::MessageLoop::current()->is_running())
88 return;
89 base::MessageLoop::current()->Quit();
92 // TestService implementation:
93 void Test(const String& test_string,
94 const Callback<void()>& callback) override {
95 context_->last_test_string = test_string;
96 callback.Run();
99 private:
100 TestContext* context_;
101 StrongBinding<TestService> binding_;
104 class TestClient {
105 public:
106 explicit TestClient(TestServicePtr service)
107 : service_(service.Pass()), quit_after_ack_(false) {}
109 void AckTest() {
110 if (quit_after_ack_)
111 base::MessageLoop::current()->Quit();
114 void Test(const std::string& test_string) {
115 quit_after_ack_ = true;
116 service_->Test(test_string,
117 base::Bind(&TestClient::AckTest, base::Unretained(this)));
120 private:
121 TestServicePtr service_;
122 bool quit_after_ack_;
123 DISALLOW_COPY_AND_ASSIGN(TestClient);
126 class TestContentHandler : public ContentHandler, public ApplicationDelegate {
127 public:
128 TestContentHandler(ApplicationConnection* connection,
129 InterfaceRequest<ContentHandler> request)
130 : binding_(this, request.Pass()) {}
132 // ContentHandler:
133 void StartApplication(InterfaceRequest<Application> application_request,
134 URLResponsePtr response) override {
135 apps_.push_back(new ApplicationImpl(this, application_request.Pass()));
138 private:
139 StrongBinding<ContentHandler> binding_;
140 ScopedVector<ApplicationImpl> apps_;
142 DISALLOW_COPY_AND_ASSIGN(TestContentHandler);
145 class TestApplicationLoader : public ApplicationLoader,
146 public ApplicationDelegate,
147 public InterfaceFactory<TestService>,
148 public InterfaceFactory<ContentHandler> {
149 public:
150 TestApplicationLoader()
151 : context_(nullptr), num_loads_(0), create_content_handler_(false) {}
153 ~TestApplicationLoader() override {
154 if (context_)
155 ++context_->num_loader_deletes;
156 test_app_.reset();
159 void set_create_content_handler(bool value) {
160 create_content_handler_ = true;
163 void set_context(TestContext* context) { context_ = context; }
164 int num_loads() const { return num_loads_; }
165 const GURL& last_requestor_url() const { return last_requestor_url_; }
167 private:
168 // ApplicationLoader implementation.
169 void Load(const GURL& url,
170 InterfaceRequest<Application> application_request) override {
171 ++num_loads_;
172 test_app_.reset(new ApplicationImpl(this, application_request.Pass()));
175 // ApplicationDelegate implementation.
176 bool ConfigureIncomingConnection(ApplicationConnection* connection) override {
177 connection->AddService<TestService>(this);
178 if (create_content_handler_)
179 connection->AddService<ContentHandler>(this);
180 last_requestor_url_ = GURL(connection->GetRemoteApplicationURL());
181 return true;
184 // InterfaceFactory<TestService> implementation.
185 void Create(ApplicationConnection* connection,
186 InterfaceRequest<TestService> request) override {
187 new TestServiceImpl(context_, request.Pass());
190 // InterfaceFactory<ContentHandler> implementation.
191 void Create(ApplicationConnection* connection,
192 InterfaceRequest<ContentHandler> request) override {
193 new TestContentHandler(connection, request.Pass());
196 scoped_ptr<ApplicationImpl> test_app_;
197 TestContext* context_;
198 int num_loads_;
199 GURL last_requestor_url_;
200 bool create_content_handler_;
202 DISALLOW_COPY_AND_ASSIGN(TestApplicationLoader);
205 class ClosingApplicationLoader : public ApplicationLoader {
206 private:
207 // ApplicationLoader implementation.
208 void Load(const GURL& url,
209 InterfaceRequest<Application> application_request) override {}
212 class TesterContext {
213 public:
214 explicit TesterContext(base::MessageLoop* loop)
215 : num_b_calls_(0),
216 num_c_calls_(0),
217 num_a_deletes_(0),
218 num_b_deletes_(0),
219 num_c_deletes_(0),
220 tester_called_quit_(false),
221 a_called_quit_(false),
222 loop_(loop) {}
224 void IncrementNumBCalls() {
225 base::AutoLock lock(lock_);
226 num_b_calls_++;
229 void IncrementNumCCalls() {
230 base::AutoLock lock(lock_);
231 num_c_calls_++;
234 void IncrementNumADeletes() {
235 base::AutoLock lock(lock_);
236 num_a_deletes_++;
239 void IncrementNumBDeletes() {
240 base::AutoLock lock(lock_);
241 num_b_deletes_++;
244 void IncrementNumCDeletes() {
245 base::AutoLock lock(lock_);
246 num_c_deletes_++;
249 void set_tester_called_quit() {
250 base::AutoLock lock(lock_);
251 tester_called_quit_ = true;
254 void set_a_called_quit() {
255 base::AutoLock lock(lock_);
256 a_called_quit_ = true;
259 int num_b_calls() {
260 base::AutoLock lock(lock_);
261 return num_b_calls_;
263 int num_c_calls() {
264 base::AutoLock lock(lock_);
265 return num_c_calls_;
267 int num_a_deletes() {
268 base::AutoLock lock(lock_);
269 return num_a_deletes_;
271 int num_b_deletes() {
272 base::AutoLock lock(lock_);
273 return num_b_deletes_;
275 int num_c_deletes() {
276 base::AutoLock lock(lock_);
277 return num_c_deletes_;
279 bool tester_called_quit() {
280 base::AutoLock lock(lock_);
281 return tester_called_quit_;
283 bool a_called_quit() {
284 base::AutoLock lock(lock_);
285 return a_called_quit_;
288 void QuitSoon() {
289 loop_->PostTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
292 private:
293 // lock_ protects all members except for loop_ which must be unchanged for the
294 // lifetime of this class.
295 base::Lock lock_;
296 int num_b_calls_;
297 int num_c_calls_;
298 int num_a_deletes_;
299 int num_b_deletes_;
300 int num_c_deletes_;
301 bool tester_called_quit_;
302 bool a_called_quit_;
304 base::MessageLoop* loop_;
307 // Used to test that the requestor url will be correctly passed.
308 class TestAImpl : public TestA {
309 public:
310 TestAImpl(ApplicationImpl* app_impl,
311 TesterContext* test_context,
312 InterfaceRequest<TestA> request)
313 : test_context_(test_context), binding_(this, request.Pass()) {
314 mojo::URLRequestPtr request2(mojo::URLRequest::New());
315 request2->url = mojo::String::From(kTestBURLString);
316 connection_ = app_impl->ConnectToApplication(request2.Pass());
317 connection_->ConnectToService(&b_);
320 ~TestAImpl() override {
321 test_context_->IncrementNumADeletes();
322 if (base::MessageLoop::current()->is_running())
323 Quit();
326 private:
327 void CallB() override {
328 b_->B(base::Bind(&TestAImpl::Quit, base::Unretained(this)));
331 void CallCFromB() override {
332 b_->CallC(base::Bind(&TestAImpl::Quit, base::Unretained(this)));
335 void Quit() {
336 base::MessageLoop::current()->Quit();
337 test_context_->set_a_called_quit();
338 test_context_->QuitSoon();
341 scoped_ptr<ApplicationConnection> connection_;
342 TesterContext* test_context_;
343 TestBPtr b_;
344 StrongBinding<TestA> binding_;
347 class TestBImpl : public TestB {
348 public:
349 TestBImpl(ApplicationConnection* connection,
350 TesterContext* test_context,
351 InterfaceRequest<TestB> request)
352 : test_context_(test_context), binding_(this, request.Pass()) {
353 connection->ConnectToService(&c_);
356 ~TestBImpl() override {
357 test_context_->IncrementNumBDeletes();
358 if (base::MessageLoop::current()->is_running())
359 base::MessageLoop::current()->Quit();
360 test_context_->QuitSoon();
363 private:
364 void B(const Callback<void()>& callback) override {
365 test_context_->IncrementNumBCalls();
366 callback.Run();
369 void CallC(const Callback<void()>& callback) override {
370 test_context_->IncrementNumBCalls();
371 c_->C(callback);
374 TesterContext* test_context_;
375 TestCPtr c_;
376 StrongBinding<TestB> binding_;
379 class TestCImpl : public TestC {
380 public:
381 TestCImpl(ApplicationConnection* connection,
382 TesterContext* test_context,
383 InterfaceRequest<TestC> request)
384 : test_context_(test_context), binding_(this, request.Pass()) {}
386 ~TestCImpl() override { test_context_->IncrementNumCDeletes(); }
388 private:
389 void C(const Callback<void()>& callback) override {
390 test_context_->IncrementNumCCalls();
391 callback.Run();
394 TesterContext* test_context_;
395 StrongBinding<TestC> binding_;
398 class Tester : public ApplicationDelegate,
399 public ApplicationLoader,
400 public InterfaceFactory<TestA>,
401 public InterfaceFactory<TestB>,
402 public InterfaceFactory<TestC> {
403 public:
404 Tester(TesterContext* context, const std::string& requestor_url)
405 : context_(context), requestor_url_(requestor_url) {}
406 ~Tester() override {}
408 private:
409 void Load(const GURL& url,
410 InterfaceRequest<Application> application_request) override {
411 app_.reset(new ApplicationImpl(this, application_request.Pass()));
414 bool ConfigureIncomingConnection(ApplicationConnection* connection) override {
415 if (!requestor_url_.empty() &&
416 requestor_url_ != connection->GetRemoteApplicationURL()) {
417 context_->set_tester_called_quit();
418 context_->QuitSoon();
419 base::MessageLoop::current()->Quit();
420 return false;
422 // If we're coming from A, then add B, otherwise A.
423 if (connection->GetRemoteApplicationURL() == kTestAURLString)
424 connection->AddService<TestB>(this);
425 else
426 connection->AddService<TestA>(this);
427 return true;
430 bool ConfigureOutgoingConnection(ApplicationConnection* connection) override {
431 // If we're connecting to B, then add C.
432 if (connection->GetRemoteApplicationURL() == kTestBURLString)
433 connection->AddService<TestC>(this);
434 return true;
437 void Create(ApplicationConnection* connection,
438 InterfaceRequest<TestA> request) override {
439 a_bindings_.push_back(new TestAImpl(app_.get(), context_, request.Pass()));
442 void Create(ApplicationConnection* connection,
443 InterfaceRequest<TestB> request) override {
444 new TestBImpl(connection, context_, request.Pass());
447 void Create(ApplicationConnection* connection,
448 InterfaceRequest<TestC> request) override {
449 new TestCImpl(connection, context_, request.Pass());
452 TesterContext* context_;
453 scoped_ptr<ApplicationImpl> app_;
454 std::string requestor_url_;
455 ScopedVector<TestAImpl> a_bindings_;
458 class TestDelegate : public ApplicationManager::Delegate {
459 public:
460 TestDelegate()
461 : create_test_fetcher_(false),
462 fetcher_url_("xxx"),
463 mime_type_(kTestMimeType) {}
464 ~TestDelegate() override {}
466 void AddMapping(const GURL& from, const GURL& to) { mappings_[from] = to; }
468 void set_create_test_fetcher(bool create_test_fetcher) {
469 create_test_fetcher_ = create_test_fetcher;
472 void set_fetcher_url(const GURL& url) { fetcher_url_ = url; }
474 void set_mime_type(const std::string& mime_type) { mime_type_ = mime_type; }
476 // ApplicationManager::Delegate
477 GURL ResolveMappings(const GURL& url) override {
478 auto it = mappings_.find(url);
479 if (it != mappings_.end())
480 return it->second;
481 return url;
483 GURL ResolveMojoURL(const GURL& url) override {
484 GURL mapped_url = ResolveMappings(url);
485 // The shell automatically map mojo URLs.
486 if (mapped_url.scheme() == "mojo") {
487 url::Replacements<char> replacements;
488 replacements.SetScheme("file", url::Component(0, 4));
489 mapped_url = mapped_url.ReplaceComponents(replacements);
491 return mapped_url;
493 bool CreateFetcher(const GURL& url,
494 const Fetcher::FetchCallback& loader_callback) override {
495 if (!create_test_fetcher_)
496 return false;
497 new TestMimeTypeFetcher(loader_callback, fetcher_url_, mime_type_);
498 return true;
501 private:
502 std::map<GURL, GURL> mappings_;
503 bool create_test_fetcher_;
504 GURL fetcher_url_;
505 std::string mime_type_;
507 DISALLOW_COPY_AND_ASSIGN(TestDelegate);
510 class ApplicationManagerTest : public testing::Test {
511 public:
512 ApplicationManagerTest() : tester_context_(&loop_) {}
514 ~ApplicationManagerTest() override {}
516 void SetUp() override {
517 application_manager_.reset(new ApplicationManager(&test_delegate_));
518 test_loader_ = new TestApplicationLoader;
519 test_loader_->set_context(&context_);
520 application_manager_->set_default_loader(
521 scoped_ptr<ApplicationLoader>(test_loader_));
523 TestServicePtr service_proxy;
524 application_manager_->ConnectToService(GURL(kTestURLString),
525 &service_proxy);
526 test_client_.reset(new TestClient(service_proxy.Pass()));
529 void TearDown() override {
530 test_client_.reset();
531 application_manager_.reset();
534 void AddLoaderForURL(const GURL& url, const std::string& requestor_url) {
535 application_manager_->SetLoaderForURL(
536 make_scoped_ptr(new Tester(&tester_context_, requestor_url)), url);
539 bool HasRunningInstanceForURL(const GURL& url) {
540 ApplicationManager::TestAPI manager_test_api(application_manager_.get());
541 return manager_test_api.HasRunningInstanceForURL(url);
544 protected:
545 base::ShadowingAtExitManager at_exit_;
546 TestDelegate test_delegate_;
547 TestApplicationLoader* test_loader_;
548 TesterContext tester_context_;
549 TestContext context_;
550 base::MessageLoop loop_;
551 scoped_ptr<TestClient> test_client_;
552 scoped_ptr<ApplicationManager> application_manager_;
553 DISALLOW_COPY_AND_ASSIGN(ApplicationManagerTest);
556 TEST_F(ApplicationManagerTest, Basic) {
557 test_client_->Test("test");
558 loop_.Run();
559 EXPECT_EQ(std::string("test"), context_.last_test_string);
562 // Confirm that url mappings are respected.
563 TEST_F(ApplicationManagerTest, URLMapping) {
564 ApplicationManager am(&test_delegate_);
565 GURL test_url("test:test");
566 GURL test_url2("test:test2");
567 test_delegate_.AddMapping(test_url, test_url2);
568 TestApplicationLoader* loader = new TestApplicationLoader;
569 loader->set_context(&context_);
570 am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(loader), test_url2);
572 // Connect to the mapped url
573 TestServicePtr test_service;
574 am.ConnectToService(test_url, &test_service);
575 TestClient test_client(test_service.Pass());
576 test_client.Test("test");
577 loop_.Run();
580 // Connect to the target url
581 TestServicePtr test_service;
582 am.ConnectToService(test_url2, &test_service);
583 TestClient test_client(test_service.Pass());
584 test_client.Test("test");
585 loop_.Run();
589 TEST_F(ApplicationManagerTest, ClientError) {
590 test_client_->Test("test");
591 EXPECT_TRUE(HasRunningInstanceForURL(GURL(kTestURLString)));
592 loop_.Run();
593 EXPECT_EQ(1, context_.num_impls);
594 test_client_.reset();
595 loop_.Run();
596 EXPECT_EQ(0, context_.num_impls);
597 EXPECT_TRUE(HasRunningInstanceForURL(GURL(kTestURLString)));
600 TEST_F(ApplicationManagerTest, Deletes) {
602 ApplicationManager am(&test_delegate_);
603 TestApplicationLoader* default_loader = new TestApplicationLoader;
604 default_loader->set_context(&context_);
605 TestApplicationLoader* url_loader1 = new TestApplicationLoader;
606 TestApplicationLoader* url_loader2 = new TestApplicationLoader;
607 url_loader1->set_context(&context_);
608 url_loader2->set_context(&context_);
609 TestApplicationLoader* scheme_loader1 = new TestApplicationLoader;
610 TestApplicationLoader* scheme_loader2 = new TestApplicationLoader;
611 scheme_loader1->set_context(&context_);
612 scheme_loader2->set_context(&context_);
613 am.set_default_loader(scoped_ptr<ApplicationLoader>(default_loader));
614 am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(url_loader1),
615 GURL("test:test1"));
616 am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(url_loader2),
617 GURL("test:test1"));
618 am.SetLoaderForScheme(scoped_ptr<ApplicationLoader>(scheme_loader1),
619 "test");
620 am.SetLoaderForScheme(scoped_ptr<ApplicationLoader>(scheme_loader2),
621 "test");
623 EXPECT_EQ(5, context_.num_loader_deletes);
626 // Confirm that both urls and schemes can have their loaders explicitly set.
627 TEST_F(ApplicationManagerTest, SetLoaders) {
628 TestApplicationLoader* default_loader = new TestApplicationLoader;
629 TestApplicationLoader* url_loader = new TestApplicationLoader;
630 TestApplicationLoader* scheme_loader = new TestApplicationLoader;
631 application_manager_->set_default_loader(
632 scoped_ptr<ApplicationLoader>(default_loader));
633 application_manager_->SetLoaderForURL(
634 scoped_ptr<ApplicationLoader>(url_loader), GURL("test:test1"));
635 application_manager_->SetLoaderForScheme(
636 scoped_ptr<ApplicationLoader>(scheme_loader), "test");
638 // test::test1 should go to url_loader.
639 TestServicePtr test_service;
640 application_manager_->ConnectToService(GURL("test:test1"), &test_service);
641 EXPECT_EQ(1, url_loader->num_loads());
642 EXPECT_EQ(0, scheme_loader->num_loads());
643 EXPECT_EQ(0, default_loader->num_loads());
645 // test::test2 should go to scheme loader.
646 application_manager_->ConnectToService(GURL("test:test2"), &test_service);
647 EXPECT_EQ(1, url_loader->num_loads());
648 EXPECT_EQ(1, scheme_loader->num_loads());
649 EXPECT_EQ(0, default_loader->num_loads());
651 // http::test1 should go to default loader.
652 application_manager_->ConnectToService(GURL("http:test1"), &test_service);
653 EXPECT_EQ(1, url_loader->num_loads());
654 EXPECT_EQ(1, scheme_loader->num_loads());
655 EXPECT_EQ(1, default_loader->num_loads());
658 // Confirm that the url of a service is correctly passed to another service that
659 // it loads.
660 TEST_F(ApplicationManagerTest, ACallB) {
661 // Any url can load a.
662 AddLoaderForURL(GURL(kTestAURLString), std::string());
664 // Only a can load b.
665 AddLoaderForURL(GURL(kTestBURLString), kTestAURLString);
667 TestAPtr a;
668 application_manager_->ConnectToService(GURL(kTestAURLString), &a);
669 a->CallB();
670 loop_.Run();
671 EXPECT_EQ(1, tester_context_.num_b_calls());
672 EXPECT_TRUE(tester_context_.a_called_quit());
675 // A calls B which calls C.
676 TEST_F(ApplicationManagerTest, BCallC) {
677 // Any url can load a.
678 AddLoaderForURL(GURL(kTestAURLString), std::string());
680 // Only a can load b.
681 AddLoaderForURL(GURL(kTestBURLString), kTestAURLString);
683 TestAPtr a;
684 application_manager_->ConnectToService(GURL(kTestAURLString), &a);
685 a->CallCFromB();
686 loop_.Run();
688 EXPECT_EQ(1, tester_context_.num_b_calls());
689 EXPECT_EQ(1, tester_context_.num_c_calls());
690 EXPECT_TRUE(tester_context_.a_called_quit());
693 // Confirm that a service impl will be deleted if the app that connected to
694 // it goes away.
695 TEST_F(ApplicationManagerTest, BDeleted) {
696 AddLoaderForURL(GURL(kTestAURLString), std::string());
697 AddLoaderForURL(GURL(kTestBURLString), std::string());
699 TestAPtr a;
700 application_manager_->ConnectToService(GURL(kTestAURLString), &a);
702 a->CallB();
703 loop_.Run();
705 // Kills the a app.
706 application_manager_->SetLoaderForURL(scoped_ptr<ApplicationLoader>(),
707 GURL(kTestAURLString));
708 loop_.Run();
710 EXPECT_EQ(1, tester_context_.num_b_deletes());
713 // Confirm that the url of a service is correctly passed to another service that
714 // it loads, and that it can be rejected.
715 TEST_F(ApplicationManagerTest, ANoLoadB) {
716 // Any url can load a.
717 AddLoaderForURL(GURL(kTestAURLString), std::string());
719 // Only c can load b, so this will fail.
720 AddLoaderForURL(GURL(kTestBURLString), "test:TestC");
722 TestAPtr a;
723 application_manager_->ConnectToService(GURL(kTestAURLString), &a);
724 a->CallB();
725 loop_.Run();
726 EXPECT_EQ(0, tester_context_.num_b_calls());
728 EXPECT_FALSE(tester_context_.a_called_quit());
729 EXPECT_TRUE(tester_context_.tester_called_quit());
732 TEST_F(ApplicationManagerTest, NoServiceNoLoad) {
733 AddLoaderForURL(GURL(kTestAURLString), std::string());
735 // There is no TestC service implementation registered with
736 // ApplicationManager, so this cannot succeed (but also shouldn't crash).
737 TestCPtr c;
738 application_manager_->ConnectToService(GURL(kTestAURLString), &c);
739 c.set_connection_error_handler(
740 []() { base::MessageLoop::current()->QuitWhenIdle(); });
742 loop_.Run();
743 EXPECT_TRUE(c.encountered_error());
746 TEST_F(ApplicationManagerTest, MappedURLsShouldNotCauseDuplicateLoad) {
747 test_delegate_.AddMapping(GURL("foo:foo2"), GURL("foo:foo"));
748 // 1 because ApplicationManagerTest connects once at startup.
749 EXPECT_EQ(1, test_loader_->num_loads());
751 TestServicePtr test_service;
752 application_manager_->ConnectToService(GURL("foo:foo"), &test_service);
753 EXPECT_EQ(2, test_loader_->num_loads());
755 TestServicePtr test_service2;
756 application_manager_->ConnectToService(GURL("foo:foo2"), &test_service2);
757 EXPECT_EQ(2, test_loader_->num_loads());
759 TestServicePtr test_service3;
760 application_manager_->ConnectToService(GURL("bar:bar"), &test_service2);
761 EXPECT_EQ(3, test_loader_->num_loads());
764 TEST_F(ApplicationManagerTest, MappedURLsShouldWorkWithLoaders) {
765 TestApplicationLoader* custom_loader = new TestApplicationLoader;
766 TestContext context;
767 custom_loader->set_context(&context);
768 application_manager_->SetLoaderForURL(make_scoped_ptr(custom_loader),
769 GURL("mojo:foo"));
770 test_delegate_.AddMapping(GURL("mojo:foo2"), GURL("mojo:foo"));
772 TestServicePtr test_service;
773 application_manager_->ConnectToService(GURL("mojo:foo2"), &test_service);
774 EXPECT_EQ(1, custom_loader->num_loads());
775 custom_loader->set_context(nullptr);
777 EXPECT_TRUE(HasRunningInstanceForURL(GURL("mojo:foo2")));
778 EXPECT_FALSE(HasRunningInstanceForURL(GURL("mojo:foo")));
781 TEST_F(ApplicationManagerTest, TestQueryWithLoaders) {
782 TestApplicationLoader* url_loader = new TestApplicationLoader;
783 TestApplicationLoader* scheme_loader = new TestApplicationLoader;
784 application_manager_->SetLoaderForURL(
785 scoped_ptr<ApplicationLoader>(url_loader), GURL("test:test1"));
786 application_manager_->SetLoaderForScheme(
787 scoped_ptr<ApplicationLoader>(scheme_loader), "test");
789 // test::test1 should go to url_loader.
790 TestServicePtr test_service;
791 application_manager_->ConnectToService(GURL("test:test1?foo=bar"),
792 &test_service);
793 EXPECT_EQ(1, url_loader->num_loads());
794 EXPECT_EQ(0, scheme_loader->num_loads());
796 // test::test2 should go to scheme loader.
797 application_manager_->ConnectToService(GURL("test:test2?foo=bar"),
798 &test_service);
799 EXPECT_EQ(1, url_loader->num_loads());
800 EXPECT_EQ(1, scheme_loader->num_loads());
803 TEST_F(ApplicationManagerTest, TestEndApplicationClosure) {
804 ClosingApplicationLoader* loader = new ClosingApplicationLoader();
805 application_manager_->SetLoaderForScheme(
806 scoped_ptr<ApplicationLoader>(loader), "test");
808 bool called = false;
809 scoped_ptr<ConnectToApplicationParams> params(new ConnectToApplicationParams);
810 params->SetURLInfo(GURL("test:test"));
811 params->set_filter(GetPermissiveCapabilityFilter());
812 params->set_on_application_end(
813 base::Bind(&QuitClosure, base::Unretained(&called)));
814 application_manager_->ConnectToApplication(params.Pass());
815 loop_.Run();
816 EXPECT_TRUE(called);
819 TEST(ApplicationManagerTest2, ContentHandlerConnectionGetsRequestorURL) {
820 const GURL content_handler_url("http://test.content.handler");
821 const GURL requestor_url("http://requestor.url");
822 TestContext test_context;
823 base::MessageLoop loop;
824 TestDelegate test_delegate;
825 test_delegate.set_create_test_fetcher(true);
826 ApplicationManager application_manager(&test_delegate);
827 application_manager.set_default_loader(nullptr);
828 application_manager.RegisterContentHandler(kTestMimeType,
829 content_handler_url);
831 TestApplicationLoader* loader = new TestApplicationLoader;
832 loader->set_context(&test_context);
833 application_manager.SetLoaderForURL(scoped_ptr<ApplicationLoader>(loader),
834 content_handler_url);
836 bool called = false;
837 scoped_ptr<ConnectToApplicationParams> params(new ConnectToApplicationParams);
838 params->set_originator_identity(Identity(requestor_url));
839 params->set_originator_filter(GetPermissiveCapabilityFilter());
840 params->SetURLInfo(GURL("test:test"));
841 params->set_filter(GetPermissiveCapabilityFilter());
842 params->set_on_application_end(
843 base::Bind(&QuitClosure, base::Unretained(&called)));
844 application_manager.ConnectToApplication(params.Pass());
845 loop.Run();
846 EXPECT_TRUE(called);
848 ASSERT_EQ(1, loader->num_loads());
849 EXPECT_EQ(requestor_url, loader->last_requestor_url());
852 TEST_F(ApplicationManagerTest, SameIdentityShouldNotCauseDuplicateLoad) {
853 // 1 because ApplicationManagerTest connects once at startup.
854 EXPECT_EQ(1, test_loader_->num_loads());
856 TestServicePtr test_service;
857 application_manager_->ConnectToService(GURL("http://www.example.org/abc?def"),
858 &test_service);
859 EXPECT_EQ(2, test_loader_->num_loads());
861 // Exactly the same URL as above.
862 application_manager_->ConnectToService(GURL("http://www.example.org/abc?def"),
863 &test_service);
864 EXPECT_EQ(2, test_loader_->num_loads());
866 // The same identity as the one above because only the query string is
867 // different.
868 application_manager_->ConnectToService(GURL("http://www.example.org/abc"),
869 &test_service);
870 EXPECT_EQ(2, test_loader_->num_loads());
872 // A different identity because the path is different.
873 application_manager_->ConnectToService(
874 GURL("http://www.example.org/another_path"), &test_service);
875 EXPECT_EQ(3, test_loader_->num_loads());
877 // A different identity because the domain is different.
878 application_manager_->ConnectToService(
879 GURL("http://www.another_domain.org/abc"), &test_service);
880 EXPECT_EQ(4, test_loader_->num_loads());
883 TEST(ApplicationManagerTest2,
884 MultipleConnectionsToContentHandlerGetSameContentHandlerId) {
885 base::MessageLoop loop;
886 const GURL content_handler_url("http://test.content.handler");
887 const GURL requestor_url("http://requestor.url");
888 TestContext test_context;
889 TestDelegate test_delegate;
890 test_delegate.set_fetcher_url(GURL("test:test"));
891 test_delegate.set_create_test_fetcher(true);
892 ApplicationManager application_manager(&test_delegate);
893 application_manager.set_default_loader(nullptr);
894 application_manager.RegisterContentHandler(kTestMimeType,
895 content_handler_url);
897 TestApplicationLoader* content_handler_loader = new TestApplicationLoader;
898 content_handler_loader->set_create_content_handler(true);
899 content_handler_loader->set_context(&test_context);
900 application_manager.SetLoaderForURL(
901 scoped_ptr<ApplicationLoader>(content_handler_loader),
902 content_handler_url);
904 uint32_t content_handler_id;
906 base::RunLoop run_loop;
907 scoped_ptr<ConnectToApplicationParams> params(
908 new ConnectToApplicationParams);
909 params->set_originator_identity(Identity(requestor_url));
910 params->set_originator_filter(GetPermissiveCapabilityFilter());
911 params->SetURLInfo(GURL("test:test"));
912 params->set_filter(GetPermissiveCapabilityFilter());
913 params->set_connect_callback([&content_handler_id, &run_loop](uint32_t t) {
914 content_handler_id = t;
915 run_loop.Quit();
917 application_manager.ConnectToApplication(params.Pass());
918 run_loop.Run();
919 EXPECT_NE(Shell::kInvalidContentHandlerID, content_handler_id);
922 uint32_t content_handler_id2;
924 base::RunLoop run_loop;
925 scoped_ptr<ConnectToApplicationParams> params(
926 new ConnectToApplicationParams);
927 params->set_originator_identity(Identity(requestor_url));
928 params->set_originator_filter(GetPermissiveCapabilityFilter());
929 params->SetURLInfo(GURL("test:test"));
930 params->set_filter(GetPermissiveCapabilityFilter());
931 params->set_connect_callback([&content_handler_id2, &run_loop](uint32_t t) {
932 content_handler_id2 = t;
933 run_loop.Quit();
935 application_manager.ConnectToApplication(params.Pass());
936 run_loop.Run();
937 EXPECT_NE(Shell::kInvalidContentHandlerID, content_handler_id2);
939 EXPECT_EQ(content_handler_id, content_handler_id2);
942 TEST(ApplicationManagerTest2, DifferedContentHandlersGetDifferentIDs) {
943 base::MessageLoop loop;
944 const GURL content_handler_url("http://test.content.handler");
945 const GURL requestor_url("http://requestor.url");
946 TestContext test_context;
947 TestDelegate test_delegate;
948 test_delegate.set_fetcher_url(GURL("test:test"));
949 test_delegate.set_create_test_fetcher(true);
950 ApplicationManager application_manager(&test_delegate);
951 application_manager.set_default_loader(nullptr);
952 application_manager.RegisterContentHandler(kTestMimeType,
953 content_handler_url);
955 TestApplicationLoader* content_handler_loader = new TestApplicationLoader;
956 content_handler_loader->set_create_content_handler(true);
957 content_handler_loader->set_context(&test_context);
958 application_manager.SetLoaderForURL(
959 scoped_ptr<ApplicationLoader>(content_handler_loader),
960 content_handler_url);
962 uint32_t content_handler_id;
964 base::RunLoop run_loop;
965 scoped_ptr<ConnectToApplicationParams> params(
966 new ConnectToApplicationParams);
967 params->set_originator_identity(Identity(requestor_url));
968 params->set_originator_filter(GetPermissiveCapabilityFilter());
969 params->SetURLInfo(GURL("test:test"));
970 params->set_filter(GetPermissiveCapabilityFilter());
971 params->set_connect_callback([&content_handler_id, &run_loop](uint32_t t) {
972 content_handler_id = t;
973 run_loop.Quit();
975 application_manager.ConnectToApplication(params.Pass());
976 run_loop.Run();
977 EXPECT_NE(Shell::kInvalidContentHandlerID, content_handler_id);
980 const std::string mime_type2("test/mime-type2");
981 const GURL content_handler_url2("http://test.content2.handler");
982 test_delegate.set_fetcher_url(GURL("test2:test2"));
983 test_delegate.set_mime_type(mime_type2);
984 application_manager.RegisterContentHandler(mime_type2, content_handler_url2);
986 TestApplicationLoader* content_handler_loader2 = new TestApplicationLoader;
987 content_handler_loader->set_create_content_handler(true);
988 content_handler_loader->set_context(&test_context);
989 application_manager.SetLoaderForURL(
990 scoped_ptr<ApplicationLoader>(content_handler_loader2),
991 content_handler_url2);
993 uint32_t content_handler_id2;
995 base::RunLoop run_loop;
996 scoped_ptr<ConnectToApplicationParams> params(
997 new ConnectToApplicationParams);
998 params->set_originator_identity(Identity(requestor_url));
999 params->set_originator_filter(GetPermissiveCapabilityFilter());
1000 params->SetURLInfo(GURL("test2:test2"));
1001 params->set_filter(GetPermissiveCapabilityFilter());
1002 params->set_connect_callback([&content_handler_id2, &run_loop](uint32_t t) {
1003 content_handler_id2 = t;
1004 run_loop.Quit();
1006 application_manager.ConnectToApplication(params.Pass());
1007 run_loop.Run();
1008 EXPECT_NE(Shell::kInvalidContentHandlerID, content_handler_id2);
1010 EXPECT_NE(content_handler_id, content_handler_id2);
1013 TEST_F(ApplicationManagerTest,
1014 ConnectWithNoContentHandlerGetsInvalidContentHandlerId) {
1015 application_manager_->SetLoaderForScheme(
1016 scoped_ptr<ApplicationLoader>(new TestApplicationLoader), "test");
1018 uint32_t content_handler_id = 1u;
1019 scoped_ptr<ConnectToApplicationParams> params(new ConnectToApplicationParams);
1020 params->SetURLInfo(GURL("test:test"));
1021 params->set_filter(GetPermissiveCapabilityFilter());
1022 params->set_connect_callback(
1023 [&content_handler_id](uint32_t t) { content_handler_id = t; });
1024 application_manager_->ConnectToApplication(params.Pass());
1025 EXPECT_EQ(0u, content_handler_id);
1028 } // namespace
1029 } // namespace shell
1030 } // namespace mojo