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