blob: 0c32de3276849b6f82d55bb5696e81692649926d [file] [log] [blame]
James Robinson646469d2014-10-03 15:33:28 -07001// 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
Viet-Trung Luu7ab22132016-04-26 21:09:03 -07005#include "shell/application_manager/application_manager.h"
6
7#include <utility>
8
James Robinson646469d2014-10-03 15:33:28 -07009#include "base/at_exit.h"
10#include "base/bind.h"
11#include "base/macros.h"
Scott Violetdd035f52014-12-18 08:47:12 -080012#include "base/memory/scoped_vector.h"
James Robinson646469d2014-10-03 15:33:28 -070013#include "base/message_loop/message_loop.h"
James Robinson646469d2014-10-03 15:33:28 -070014#include "mojo/public/cpp/application/application_delegate.h"
15#include "mojo/public/cpp/application/application_impl.h"
Viet-Trung Luu7ab22132016-04-26 21:09:03 -070016#include "mojo/public/cpp/application/connect.h"
Viet-Trung Luub237bca2016-05-13 16:35:11 -070017#include "mojo/public/cpp/application/service_provider_impl.h"
Dave Moore2abdce52015-01-26 15:41:12 -080018#include "mojo/public/cpp/bindings/strong_binding.h"
James Robinson646469d2014-10-03 15:33:28 -070019#include "mojo/public/interfaces/application/service_provider.mojom.h"
Przemysław Pietrzkiewicz6384d092015-01-15 16:03:17 -080020#include "shell/application_manager/application_loader.h"
Przemysław Pietrzkiewicz6384d092015-01-15 16:03:17 -080021#include "shell/application_manager/test.mojom.h"
James Robinson646469d2014-10-03 15:33:28 -070022#include "testing/gtest/include/gtest/gtest.h"
23
Viet-Trung Luue377a9e2015-04-09 13:53:21 -070024using mojo::Application;
Viet-Trung Luue377a9e2015-04-09 13:53:21 -070025using mojo::ApplicationDelegate;
26using mojo::ApplicationImpl;
27using mojo::Callback;
Viet-Trung Luud21f93b2016-05-12 16:35:38 -070028using mojo::ConnectionContext;
Viet-Trung Luue377a9e2015-04-09 13:53:21 -070029using mojo::InterfaceRequest;
30using mojo::StrongBinding;
31
Viet-Trung Luu36faa4d2015-03-04 18:08:18 -080032namespace shell {
James Robinson646469d2014-10-03 15:33:28 -070033namespace {
34
35const char kTestURLString[] = "test:testService";
36const char kTestAURLString[] = "test:TestA";
37const char kTestBURLString[] = "test:TestB";
38
39struct TestContext {
40 TestContext() : num_impls(0), num_loader_deletes(0) {}
41 std::string last_test_string;
42 int num_impls;
43 int num_loader_deletes;
44};
45
Benjamin Lerman993869e2015-03-24 13:35:28 +010046void QuitClosure(bool* value) {
47 *value = true;
48 base::MessageLoop::current()->QuitWhenIdle();
49}
50
Dave Moore2abdce52015-01-26 15:41:12 -080051class TestServiceImpl : public TestService {
James Robinson646469d2014-10-03 15:33:28 -070052 public:
Viet-Trung Luue377a9e2015-04-09 13:53:21 -070053 TestServiceImpl(TestContext* context, InterfaceRequest<TestService> request)
Dave Moore2abdce52015-01-26 15:41:12 -080054 : context_(context), binding_(this, request.Pass()) {
James Robinson646469d2014-10-03 15:33:28 -070055 ++context_->num_impls;
56 }
57
Dave Moore2abdce52015-01-26 15:41:12 -080058 ~TestServiceImpl() override {
59 --context_->num_impls;
James Robinson646469d2014-10-03 15:33:28 -070060 if (!base::MessageLoop::current()->is_running())
61 return;
62 base::MessageLoop::current()->Quit();
63 }
64
65 // TestService implementation:
Viet-Trung Luubd07e3a2015-04-09 12:43:29 -070066 void Test(const mojo::String& test_string,
Viet-Trung Luue377a9e2015-04-09 13:53:21 -070067 const Callback<void()>& callback) override {
James Robinson646469d2014-10-03 15:33:28 -070068 context_->last_test_string = test_string;
Aaron Boodman8b78ea32015-01-21 09:28:10 -080069 callback.Run();
James Robinson646469d2014-10-03 15:33:28 -070070 }
71
72 private:
73 TestContext* context_;
Viet-Trung Luue377a9e2015-04-09 13:53:21 -070074 StrongBinding<TestService> binding_;
James Robinson646469d2014-10-03 15:33:28 -070075};
76
Aaron Boodman8b78ea32015-01-21 09:28:10 -080077class TestClient {
James Robinson646469d2014-10-03 15:33:28 -070078 public:
Aaron Boodman8b78ea32015-01-21 09:28:10 -080079 explicit TestClient(TestServicePtr service)
80 : service_(service.Pass()), quit_after_ack_(false) {}
James Robinson646469d2014-10-03 15:33:28 -070081
Aaron Boodman8b78ea32015-01-21 09:28:10 -080082 void AckTest() {
James Robinson646469d2014-10-03 15:33:28 -070083 if (quit_after_ack_)
84 base::MessageLoop::current()->Quit();
85 }
86
Scott Violetdd035f52014-12-18 08:47:12 -080087 void Test(const std::string& test_string) {
James Robinson646469d2014-10-03 15:33:28 -070088 quit_after_ack_ = true;
Aaron Boodman8b78ea32015-01-21 09:28:10 -080089 service_->Test(test_string,
90 base::Bind(&TestClient::AckTest, base::Unretained(this)));
James Robinson646469d2014-10-03 15:33:28 -070091 }
92
93 private:
94 TestServicePtr service_;
95 bool quit_after_ack_;
Aaron Boodman8b78ea32015-01-21 09:28:10 -080096 DISALLOW_COPY_AND_ASSIGN(TestClient);
James Robinson646469d2014-10-03 15:33:28 -070097};
98
99class TestApplicationLoader : public ApplicationLoader,
Viet-Trung Luu5e30a072016-05-13 14:12:59 -0700100 public ApplicationDelegate {
James Robinson646469d2014-10-03 15:33:28 -0700101 public:
Viet-Trung Luua417b142015-03-31 11:24:44 -0700102 TestApplicationLoader() : context_(nullptr), num_loads_(0) {}
James Robinson646469d2014-10-03 15:33:28 -0700103
James Robinsone1b30cf2014-10-21 12:25:40 -0700104 ~TestApplicationLoader() override {
James Robinson646469d2014-10-03 15:33:28 -0700105 if (context_)
106 ++context_->num_loader_deletes;
Viet-Trung Luua417b142015-03-31 11:24:44 -0700107 test_app_.reset();
James Robinson646469d2014-10-03 15:33:28 -0700108 }
109
110 void set_context(TestContext* context) { context_ = context; }
111 int num_loads() const { return num_loads_; }
James Robinsond4531882014-10-17 16:14:32 -0700112 const std::vector<std::string>& GetArgs() const { return test_app_->args(); }
James Robinson646469d2014-10-03 15:33:28 -0700113
114 private:
115 // ApplicationLoader implementation.
Viet-Trung Luue377a9e2015-04-09 13:53:21 -0700116 void Load(const GURL& url,
117 InterfaceRequest<Application> application_request) override {
James Robinson646469d2014-10-03 15:33:28 -0700118 ++num_loads_;
Viet-Trung Luue377a9e2015-04-09 13:53:21 -0700119 test_app_.reset(new ApplicationImpl(this, application_request.Pass()));
James Robinson646469d2014-10-03 15:33:28 -0700120 }
121
Viet-Trung Luue377a9e2015-04-09 13:53:21 -0700122 // ApplicationDelegate implementation.
Viet-Trung Luu22e78b32016-05-13 15:27:15 -0700123 bool ConfigureIncomingConnection(
124 mojo::ServiceProviderImpl* service_provider_impl) override {
125 service_provider_impl->AddService<TestService>(
Viet-Trung Luu5e30a072016-05-13 14:12:59 -0700126 [this](const ConnectionContext& connection_context,
127 InterfaceRequest<TestService> request) {
128 new TestServiceImpl(context_, request.Pass());
129 });
James Robinson646469d2014-10-03 15:33:28 -0700130 return true;
131 }
132
Viet-Trung Luue377a9e2015-04-09 13:53:21 -0700133 scoped_ptr<ApplicationImpl> test_app_;
James Robinson646469d2014-10-03 15:33:28 -0700134 TestContext* context_;
135 int num_loads_;
136 DISALLOW_COPY_AND_ASSIGN(TestApplicationLoader);
137};
138
Benjamin Lerman993869e2015-03-24 13:35:28 +0100139class ClosingApplicationLoader : public ApplicationLoader {
140 private:
141 // ApplicationLoader implementation.
Viet-Trung Luue377a9e2015-04-09 13:53:21 -0700142 void Load(const GURL& url,
143 InterfaceRequest<Application> application_request) override {}
Benjamin Lerman993869e2015-03-24 13:35:28 +0100144};
145
James Robinson646469d2014-10-03 15:33:28 -0700146class TesterContext {
147 public:
148 explicit TesterContext(base::MessageLoop* loop)
149 : num_b_calls_(0),
150 num_c_calls_(0),
151 num_a_deletes_(0),
152 num_b_deletes_(0),
153 num_c_deletes_(0),
154 tester_called_quit_(false),
155 a_called_quit_(false),
156 loop_(loop) {}
157
158 void IncrementNumBCalls() {
159 base::AutoLock lock(lock_);
160 num_b_calls_++;
161 }
162
163 void IncrementNumCCalls() {
164 base::AutoLock lock(lock_);
165 num_c_calls_++;
166 }
167
168 void IncrementNumADeletes() {
169 base::AutoLock lock(lock_);
170 num_a_deletes_++;
171 }
172
173 void IncrementNumBDeletes() {
174 base::AutoLock lock(lock_);
175 num_b_deletes_++;
176 }
177
178 void IncrementNumCDeletes() {
179 base::AutoLock lock(lock_);
180 num_c_deletes_++;
181 }
182
183 void set_tester_called_quit() {
184 base::AutoLock lock(lock_);
185 tester_called_quit_ = true;
186 }
187
188 void set_a_called_quit() {
189 base::AutoLock lock(lock_);
190 a_called_quit_ = true;
191 }
192
193 int num_b_calls() {
194 base::AutoLock lock(lock_);
195 return num_b_calls_;
196 }
197 int num_c_calls() {
198 base::AutoLock lock(lock_);
199 return num_c_calls_;
200 }
201 int num_a_deletes() {
202 base::AutoLock lock(lock_);
203 return num_a_deletes_;
204 }
205 int num_b_deletes() {
206 base::AutoLock lock(lock_);
207 return num_b_deletes_;
208 }
209 int num_c_deletes() {
210 base::AutoLock lock(lock_);
211 return num_c_deletes_;
212 }
213 bool tester_called_quit() {
214 base::AutoLock lock(lock_);
215 return tester_called_quit_;
216 }
217 bool a_called_quit() {
218 base::AutoLock lock(lock_);
219 return a_called_quit_;
220 }
221
222 void QuitSoon() {
223 loop_->PostTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
224 }
225
226 private:
227 // lock_ protects all members except for loop_ which must be unchanged for the
228 // lifetime of this class.
229 base::Lock lock_;
230 int num_b_calls_;
231 int num_c_calls_;
232 int num_a_deletes_;
233 int num_b_deletes_;
234 int num_c_deletes_;
235 bool tester_called_quit_;
236 bool a_called_quit_;
237
238 base::MessageLoop* loop_;
239};
240
241// Used to test that the requestor url will be correctly passed.
Scott Violetdd035f52014-12-18 08:47:12 -0800242class TestAImpl : public TestA {
James Robinson646469d2014-10-03 15:33:28 -0700243 public:
Viet-Trung Luu7ab22132016-04-26 21:09:03 -0700244 TestAImpl(mojo::InterfaceHandle<mojo::ServiceProvider> b_sp_handle,
Scott Violetdd035f52014-12-18 08:47:12 -0800245 TesterContext* test_context,
Viet-Trung Luue377a9e2015-04-09 13:53:21 -0700246 InterfaceRequest<TestA> request)
Geoffrey Gowan8e12b962015-02-09 16:45:05 -0800247 : test_context_(test_context), binding_(this, request.Pass()) {
Viet-Trung Luu7ab22132016-04-26 21:09:03 -0700248 auto b_sp = mojo::ServiceProviderPtr::Create(b_sp_handle.Pass());
249 mojo::ConnectToService(b_sp.get(), GetProxy(&b_));
James Robinson646469d2014-10-03 15:33:28 -0700250 }
Dave Moore2abdce52015-01-26 15:41:12 -0800251
James Robinsone1b30cf2014-10-21 12:25:40 -0700252 ~TestAImpl() override {
James Robinson646469d2014-10-03 15:33:28 -0700253 test_context_->IncrementNumADeletes();
254 if (base::MessageLoop::current()->is_running())
255 Quit();
256 }
257
258 private:
James Robinsone1b30cf2014-10-21 12:25:40 -0700259 void CallB() override {
James Robinson646469d2014-10-03 15:33:28 -0700260 b_->B(base::Bind(&TestAImpl::Quit, base::Unretained(this)));
261 }
262
James Robinson646469d2014-10-03 15:33:28 -0700263 void Quit() {
264 base::MessageLoop::current()->Quit();
265 test_context_->set_a_called_quit();
266 test_context_->QuitSoon();
267 }
268
269 TesterContext* test_context_;
270 TestBPtr b_;
Viet-Trung Luue377a9e2015-04-09 13:53:21 -0700271 StrongBinding<TestA> binding_;
James Robinson646469d2014-10-03 15:33:28 -0700272};
273
Dave Moore2abdce52015-01-26 15:41:12 -0800274class TestBImpl : public TestB {
James Robinson646469d2014-10-03 15:33:28 -0700275 public:
Viet-Trung Luud21f93b2016-05-12 16:35:38 -0700276 TestBImpl(TesterContext* test_context, InterfaceRequest<TestB> request)
Viet-Trung Luu7f38d692016-05-09 12:53:14 -0700277 : test_context_(test_context), binding_(this, request.Pass()) {}
James Robinson646469d2014-10-03 15:33:28 -0700278
James Robinsone1b30cf2014-10-21 12:25:40 -0700279 ~TestBImpl() override {
James Robinson646469d2014-10-03 15:33:28 -0700280 test_context_->IncrementNumBDeletes();
281 if (base::MessageLoop::current()->is_running())
282 base::MessageLoop::current()->Quit();
283 test_context_->QuitSoon();
284 }
285
286 private:
Viet-Trung Luue377a9e2015-04-09 13:53:21 -0700287 void B(const Callback<void()>& callback) override {
James Robinson646469d2014-10-03 15:33:28 -0700288 test_context_->IncrementNumBCalls();
289 callback.Run();
290 }
291
James Robinson646469d2014-10-03 15:33:28 -0700292 TesterContext* test_context_;
Viet-Trung Luue377a9e2015-04-09 13:53:21 -0700293 StrongBinding<TestB> binding_;
James Robinson646469d2014-10-03 15:33:28 -0700294};
295
Viet-Trung Luu5e30a072016-05-13 14:12:59 -0700296class Tester : public ApplicationDelegate, public ApplicationLoader {
James Robinson646469d2014-10-03 15:33:28 -0700297 public:
298 Tester(TesterContext* context, const std::string& requestor_url)
299 : context_(context), requestor_url_(requestor_url) {}
James Robinsone1b30cf2014-10-21 12:25:40 -0700300 ~Tester() override {}
James Robinson646469d2014-10-03 15:33:28 -0700301
302 private:
Viet-Trung Luue377a9e2015-04-09 13:53:21 -0700303 void Load(const GURL& url,
304 InterfaceRequest<Application> application_request) override {
305 app_.reset(new ApplicationImpl(this, application_request.Pass()));
James Robinson646469d2014-10-03 15:33:28 -0700306 }
307
Viet-Trung Luu22e78b32016-05-13 15:27:15 -0700308 bool ConfigureIncomingConnection(
309 mojo::ServiceProviderImpl* service_provider_impl) override {
Viet-Trung Luu087fc162016-05-13 11:15:55 -0700310 const std::string& remote_url =
Viet-Trung Luu22e78b32016-05-13 15:27:15 -0700311 service_provider_impl->connection_context().remote_url;
Viet-Trung Luu087fc162016-05-13 11:15:55 -0700312 if (!requestor_url_.empty() && requestor_url_ != remote_url) {
James Robinson646469d2014-10-03 15:33:28 -0700313 context_->set_tester_called_quit();
314 context_->QuitSoon();
315 base::MessageLoop::current()->Quit();
316 return false;
317 }
318 // If we're coming from A, then add B, otherwise A.
Viet-Trung Luu5e30a072016-05-13 14:12:59 -0700319 if (remote_url == kTestAURLString) {
Viet-Trung Luu22e78b32016-05-13 15:27:15 -0700320 service_provider_impl->AddService<TestB>(
Viet-Trung Luu5e30a072016-05-13 14:12:59 -0700321 [this](const ConnectionContext& connection_context,
322 InterfaceRequest<TestB> test_b_request) {
323 new TestBImpl(context_, test_b_request.Pass());
324 });
325 } else {
Viet-Trung Luu22e78b32016-05-13 15:27:15 -0700326 service_provider_impl->AddService<TestA>(
Viet-Trung Luu5e30a072016-05-13 14:12:59 -0700327 [this](const ConnectionContext& connection_context,
328 InterfaceRequest<TestA> test_a_request) {
329 mojo::InterfaceHandle<mojo::ServiceProvider> incoming_sp_handle;
330 app_->shell()->ConnectToApplication(
331 kTestBURLString, GetProxy(&incoming_sp_handle), nullptr);
332 a_bindings_.push_back(new TestAImpl(
333 incoming_sp_handle.Pass(), context_, test_a_request.Pass()));
334 });
335 }
James Robinson646469d2014-10-03 15:33:28 -0700336 return true;
337 }
338
James Robinson646469d2014-10-03 15:33:28 -0700339 TesterContext* context_;
Viet-Trung Luue377a9e2015-04-09 13:53:21 -0700340 scoped_ptr<ApplicationImpl> app_;
James Robinson646469d2014-10-03 15:33:28 -0700341 std::string requestor_url_;
Scott Violetdd035f52014-12-18 08:47:12 -0800342 ScopedVector<TestAImpl> a_bindings_;
James Robinson646469d2014-10-03 15:33:28 -0700343};
344
Aaron Boodmancd7b9112014-11-06 21:44:49 -0800345class TestDelegate : public ApplicationManager::Delegate {
346 public:
Viet-Trung Luu32952272015-02-11 16:32:03 -0800347 void AddMapping(const GURL& from, const GURL& to) { mappings_[from] = to; }
Aaron Boodmancd7b9112014-11-06 21:44:49 -0800348
349 // ApplicationManager::Delegate
Viet-Trung Luu32952272015-02-11 16:32:03 -0800350 GURL ResolveMappings(const GURL& url) override {
Aaron Boodmancd7b9112014-11-06 21:44:49 -0800351 auto it = mappings_.find(url);
352 if (it != mappings_.end())
353 return it->second;
354 return url;
355 }
Benjamin Lerman605969e2015-04-30 13:51:04 +0200356 GURL ResolveMojoURL(const GURL& url) override {
Benjamin Lerman75aef1d2015-01-21 12:04:39 +0100357 GURL mapped_url = ResolveMappings(url);
358 // The shell automatically map mojo URLs.
359 if (mapped_url.scheme() == "mojo") {
360 url::Replacements<char> replacements;
361 replacements.SetScheme("file", url::Component(0, 4));
362 mapped_url = mapped_url.ReplaceComponents(replacements);
363 }
364 return mapped_url;
365 }
366
Aaron Boodmancd7b9112014-11-06 21:44:49 -0800367 private:
368 std::map<GURL, GURL> mappings_;
369};
370
Viet-Trung Luue377a9e2015-04-09 13:53:21 -0700371class TestExternal : public ApplicationDelegate {
Dave Moore0504d062015-01-23 15:33:29 -0800372 public:
Dave Mooref2efe552015-01-26 14:31:45 -0800373 TestExternal() : configure_incoming_connection_called_(false) {}
Dave Moore0504d062015-01-23 15:33:29 -0800374
Viet-Trung Luue377a9e2015-04-09 13:53:21 -0700375 void Initialize(ApplicationImpl* app) override {
Dave Mooref2efe552015-01-26 14:31:45 -0800376 initialize_args_ = app->args();
Dave Moore0504d062015-01-23 15:33:29 -0800377 base::MessageLoop::current()->Quit();
378 }
379
Viet-Trung Luu22e78b32016-05-13 15:27:15 -0700380 bool ConfigureIncomingConnection(
381 mojo::ServiceProviderImpl* service_provider_impl) override {
Dave Moore0504d062015-01-23 15:33:29 -0800382 configure_incoming_connection_called_ = true;
383 base::MessageLoop::current()->Quit();
384 return true;
385 }
386
Dave Mooref2efe552015-01-26 14:31:45 -0800387 const std::vector<std::string>& initialize_args() const {
388 return initialize_args_;
389 }
390
Dave Moore0504d062015-01-23 15:33:29 -0800391 bool configure_incoming_connection_called() const {
392 return configure_incoming_connection_called_;
393 }
394
395 private:
Dave Mooref2efe552015-01-26 14:31:45 -0800396 std::vector<std::string> initialize_args_;
Dave Moore0504d062015-01-23 15:33:29 -0800397 bool configure_incoming_connection_called_;
398};
399
James Robinson646469d2014-10-03 15:33:28 -0700400class ApplicationManagerTest : public testing::Test {
401 public:
402 ApplicationManagerTest() : tester_context_(&loop_) {}
403
Viet-Trung Luu153dd212014-10-21 14:41:15 -0700404 ~ApplicationManagerTest() override {}
James Robinson646469d2014-10-03 15:33:28 -0700405
Viet-Trung Luu153dd212014-10-21 14:41:15 -0700406 void SetUp() override {
Viet-Trung Luu988b4be2015-05-15 13:00:15 -0700407 application_manager_.reset(
408 new ApplicationManager(ApplicationManager::Options(), &test_delegate_));
Aaron Boodmancd7b9112014-11-06 21:44:49 -0800409 test_loader_ = new TestApplicationLoader;
410 test_loader_->set_context(&context_);
James Robinson646469d2014-10-03 15:33:28 -0700411 application_manager_->set_default_loader(
Aaron Boodmancd7b9112014-11-06 21:44:49 -0800412 scoped_ptr<ApplicationLoader>(test_loader_));
James Robinson646469d2014-10-03 15:33:28 -0700413
414 TestServicePtr service_proxy;
415 application_manager_->ConnectToService(GURL(kTestURLString),
416 &service_proxy);
Aaron Boodman8b78ea32015-01-21 09:28:10 -0800417 test_client_.reset(new TestClient(service_proxy.Pass()));
James Robinson646469d2014-10-03 15:33:28 -0700418 }
419
Viet-Trung Luu153dd212014-10-21 14:41:15 -0700420 void TearDown() override {
Viet-Trung Luua417b142015-03-31 11:24:44 -0700421 test_client_.reset();
422 application_manager_.reset();
James Robinson646469d2014-10-03 15:33:28 -0700423 }
424
James Robinson646469d2014-10-03 15:33:28 -0700425 void AddLoaderForURL(const GURL& url, const std::string& requestor_url) {
Scott Violetdd035f52014-12-18 08:47:12 -0800426 application_manager_->SetLoaderForURL(
427 make_scoped_ptr(new Tester(&tester_context_, requestor_url)), url);
James Robinson646469d2014-10-03 15:33:28 -0700428 }
429
430 bool HasFactoryForTestURL() {
431 ApplicationManager::TestAPI manager_test_api(application_manager_.get());
432 return manager_test_api.HasFactoryForURL(GURL(kTestURLString));
433 }
434
435 protected:
436 base::ShadowingAtExitManager at_exit_;
Aaron Boodmancd7b9112014-11-06 21:44:49 -0800437 TestDelegate test_delegate_;
438 TestApplicationLoader* test_loader_;
James Robinson646469d2014-10-03 15:33:28 -0700439 TesterContext tester_context_;
440 TestContext context_;
441 base::MessageLoop loop_;
Aaron Boodman8b78ea32015-01-21 09:28:10 -0800442 scoped_ptr<TestClient> test_client_;
James Robinson646469d2014-10-03 15:33:28 -0700443 scoped_ptr<ApplicationManager> application_manager_;
444 DISALLOW_COPY_AND_ASSIGN(ApplicationManagerTest);
445};
446
447TEST_F(ApplicationManagerTest, Basic) {
448 test_client_->Test("test");
449 loop_.Run();
450 EXPECT_EQ(std::string("test"), context_.last_test_string);
451}
452
453// Confirm that no arguments are sent to an application by default.
454TEST_F(ApplicationManagerTest, NoArgs) {
Viet-Trung Luu988b4be2015-05-15 13:00:15 -0700455 ApplicationManager am(ApplicationManager::Options(), &test_delegate_);
James Robinson646469d2014-10-03 15:33:28 -0700456 GURL test_url("test:test");
James Robinson646469d2014-10-03 15:33:28 -0700457 TestApplicationLoader* loader = new TestApplicationLoader;
Scott Violetba1f42c2014-12-04 11:08:49 -0800458 loader->set_context(&context_);
James Robinson646469d2014-10-03 15:33:28 -0700459 am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(loader), test_url);
460 TestServicePtr test_service;
461 am.ConnectToService(test_url, &test_service);
Aaron Boodman8b78ea32015-01-21 09:28:10 -0800462 TestClient test_client(test_service.Pass());
James Robinson646469d2014-10-03 15:33:28 -0700463 test_client.Test("test");
464 loop_.Run();
465 std::vector<std::string> app_args = loader->GetArgs();
466 EXPECT_EQ(0U, app_args.size());
467}
468
469// Confirm that arguments are sent to an application.
470TEST_F(ApplicationManagerTest, Args) {
Viet-Trung Luu988b4be2015-05-15 13:00:15 -0700471 ApplicationManager am(ApplicationManager::Options(), &test_delegate_);
James Robinson646469d2014-10-03 15:33:28 -0700472 GURL test_url("test:test");
473 std::vector<std::string> args;
474 args.push_back("test_arg1");
475 args.push_back("test_arg2");
476 am.SetArgsForURL(args, test_url);
James Robinson646469d2014-10-03 15:33:28 -0700477 TestApplicationLoader* loader = new TestApplicationLoader;
Scott Violetba1f42c2014-12-04 11:08:49 -0800478 loader->set_context(&context_);
James Robinson646469d2014-10-03 15:33:28 -0700479 am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(loader), test_url);
480 TestServicePtr test_service;
481 am.ConnectToService(test_url, &test_service);
Aaron Boodman8b78ea32015-01-21 09:28:10 -0800482 TestClient test_client(test_service.Pass());
James Robinson646469d2014-10-03 15:33:28 -0700483 test_client.Test("test");
484 loop_.Run();
485 std::vector<std::string> app_args = loader->GetArgs();
Benjamin Lermanf3b7f562015-11-23 18:18:03 +0100486 ASSERT_EQ(args.size() + 1, app_args.size());
487 EXPECT_EQ(args[0], app_args[1]);
488 EXPECT_EQ(args[1], app_args[2]);
James Robinson646469d2014-10-03 15:33:28 -0700489}
490
Benjamin Lermanaec7ef82015-11-23 15:34:06 +0100491// Confirm that arguments are sent to an application in the presence of query
492// parameters.
493TEST_F(ApplicationManagerTest, ArgsWithQuery) {
494 ApplicationManager am(ApplicationManager::Options(), &test_delegate_);
495 GURL test_url("test:test");
496 GURL test_url_with_query("test:test?foo=bar");
497 std::vector<std::string> args;
498 args.push_back("test_arg1");
499 am.SetArgsForURL(args, test_url);
500 TestApplicationLoader* loader = new TestApplicationLoader;
501 loader->set_context(&context_);
502 am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(loader), test_url);
503 TestServicePtr test_service;
504 am.ConnectToService(test_url_with_query, &test_service);
505 TestClient test_client(test_service.Pass());
506 test_client.Test("test");
507 loop_.Run();
508 std::vector<std::string> app_args = loader->GetArgs();
Benjamin Lermanf3b7f562015-11-23 18:18:03 +0100509 ASSERT_EQ(args.size() + 1, app_args.size());
510 EXPECT_EQ(args[0], app_args[1]);
511}
512
513// Confirm that the URL is not duplicated when arguments are added in multiple
514// phases.
515TEST_F(ApplicationManagerTest, ArgsMultipleCalls) {
516 ApplicationManager am(ApplicationManager::Options(), &test_delegate_);
517 GURL test_url("test:test");
518 std::vector<std::string> args1;
519 args1.push_back("test_arg1");
520 am.SetArgsForURL(args1, test_url);
521 std::vector<std::string> args2;
522 args2.push_back("test_arg2");
523 am.SetArgsForURL(args2, test_url);
524 TestApplicationLoader* loader = new TestApplicationLoader;
525 loader->set_context(&context_);
526 am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(loader), test_url);
527 TestServicePtr test_service;
528 am.ConnectToService(test_url, &test_service);
529 TestClient test_client(test_service.Pass());
530 test_client.Test("test");
531 loop_.Run();
532 std::vector<std::string> app_args = loader->GetArgs();
533 ASSERT_EQ(args1.size() + args2.size() + 1, app_args.size());
534 EXPECT_EQ(args1[0], app_args[1]);
535 EXPECT_EQ(args2[0], app_args[2]);
Benjamin Lermanaec7ef82015-11-23 15:34:06 +0100536}
537
Benjamin Lermanacf32fb2015-03-24 10:54:37 +0100538// Confirm that arguments are aggregated through mappings.
539TEST_F(ApplicationManagerTest, ArgsAndMapping) {
Viet-Trung Luu988b4be2015-05-15 13:00:15 -0700540 ApplicationManager am(ApplicationManager::Options(), &test_delegate_);
Benjamin Lermanacf32fb2015-03-24 10:54:37 +0100541 GURL test_url("test:test");
542 GURL test_url2("test:test2");
543 test_delegate_.AddMapping(test_url, test_url2);
544 std::vector<std::string> args;
545 args.push_back("test_arg1");
546 args.push_back("test_arg2");
547 am.SetArgsForURL(args, test_url);
548 std::vector<std::string> args2;
549 args2.push_back("test_arg3");
550 args2.push_back("test_arg4");
551 am.SetArgsForURL(args2, test_url2);
552 TestApplicationLoader* loader = new TestApplicationLoader;
553 loader->set_context(&context_);
554 am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(loader), test_url2);
555 {
556 // Connext to the mapped url
557 TestServicePtr test_service;
558 am.ConnectToService(test_url, &test_service);
559 TestClient test_client(test_service.Pass());
560 test_client.Test("test");
561 loop_.Run();
562 std::vector<std::string> app_args = loader->GetArgs();
Benjamin Lermanf3b7f562015-11-23 18:18:03 +0100563 ASSERT_EQ(args.size() + args2.size() + 1, app_args.size());
564 EXPECT_EQ(args[0], app_args[1]);
565 EXPECT_EQ(args[1], app_args[2]);
566 EXPECT_EQ(args2[0], app_args[3]);
567 EXPECT_EQ(args2[1], app_args[4]);
Benjamin Lermanacf32fb2015-03-24 10:54:37 +0100568 }
569 {
570 // Connext to the target url
571 TestServicePtr test_service;
572 am.ConnectToService(test_url2, &test_service);
573 TestClient test_client(test_service.Pass());
574 test_client.Test("test");
575 loop_.Run();
576 std::vector<std::string> app_args = loader->GetArgs();
Benjamin Lermanf3b7f562015-11-23 18:18:03 +0100577 ASSERT_EQ(args.size() + args2.size() + 1, app_args.size());
578 EXPECT_EQ(args[0], app_args[1]);
579 EXPECT_EQ(args[1], app_args[2]);
580 EXPECT_EQ(args2[0], app_args[3]);
581 EXPECT_EQ(args2[1], app_args[4]);
Benjamin Lermanacf32fb2015-03-24 10:54:37 +0100582 }
583}
584
James Robinson646469d2014-10-03 15:33:28 -0700585TEST_F(ApplicationManagerTest, ClientError) {
586 test_client_->Test("test");
587 EXPECT_TRUE(HasFactoryForTestURL());
588 loop_.Run();
589 EXPECT_EQ(1, context_.num_impls);
Viet-Trung Luua417b142015-03-31 11:24:44 -0700590 test_client_.reset();
James Robinson646469d2014-10-03 15:33:28 -0700591 loop_.Run();
592 EXPECT_EQ(0, context_.num_impls);
593 EXPECT_TRUE(HasFactoryForTestURL());
594}
595
596TEST_F(ApplicationManagerTest, Deletes) {
597 {
Viet-Trung Luu988b4be2015-05-15 13:00:15 -0700598 ApplicationManager am(ApplicationManager::Options(), &test_delegate_);
James Robinson646469d2014-10-03 15:33:28 -0700599 TestApplicationLoader* default_loader = new TestApplicationLoader;
600 default_loader->set_context(&context_);
601 TestApplicationLoader* url_loader1 = new TestApplicationLoader;
602 TestApplicationLoader* url_loader2 = new TestApplicationLoader;
603 url_loader1->set_context(&context_);
604 url_loader2->set_context(&context_);
605 TestApplicationLoader* scheme_loader1 = new TestApplicationLoader;
606 TestApplicationLoader* scheme_loader2 = new TestApplicationLoader;
607 scheme_loader1->set_context(&context_);
608 scheme_loader2->set_context(&context_);
609 am.set_default_loader(scoped_ptr<ApplicationLoader>(default_loader));
610 am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(url_loader1),
611 GURL("test:test1"));
612 am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(url_loader2),
613 GURL("test:test1"));
614 am.SetLoaderForScheme(scoped_ptr<ApplicationLoader>(scheme_loader1),
615 "test");
616 am.SetLoaderForScheme(scoped_ptr<ApplicationLoader>(scheme_loader2),
617 "test");
618 }
619 EXPECT_EQ(5, context_.num_loader_deletes);
620}
621
622// Confirm that both urls and schemes can have their loaders explicitly set.
623TEST_F(ApplicationManagerTest, SetLoaders) {
624 TestApplicationLoader* default_loader = new TestApplicationLoader;
625 TestApplicationLoader* url_loader = new TestApplicationLoader;
626 TestApplicationLoader* scheme_loader = new TestApplicationLoader;
627 application_manager_->set_default_loader(
628 scoped_ptr<ApplicationLoader>(default_loader));
629 application_manager_->SetLoaderForURL(
630 scoped_ptr<ApplicationLoader>(url_loader), GURL("test:test1"));
631 application_manager_->SetLoaderForScheme(
632 scoped_ptr<ApplicationLoader>(scheme_loader), "test");
633
634 // test::test1 should go to url_loader.
635 TestServicePtr test_service;
636 application_manager_->ConnectToService(GURL("test:test1"), &test_service);
637 EXPECT_EQ(1, url_loader->num_loads());
638 EXPECT_EQ(0, scheme_loader->num_loads());
639 EXPECT_EQ(0, default_loader->num_loads());
640
641 // test::test2 should go to scheme loader.
642 application_manager_->ConnectToService(GURL("test:test2"), &test_service);
643 EXPECT_EQ(1, url_loader->num_loads());
644 EXPECT_EQ(1, scheme_loader->num_loads());
645 EXPECT_EQ(0, default_loader->num_loads());
646
647 // http::test1 should go to default loader.
648 application_manager_->ConnectToService(GURL("http:test1"), &test_service);
649 EXPECT_EQ(1, url_loader->num_loads());
650 EXPECT_EQ(1, scheme_loader->num_loads());
651 EXPECT_EQ(1, default_loader->num_loads());
652}
653
654// Confirm that the url of a service is correctly passed to another service that
655// it loads.
656TEST_F(ApplicationManagerTest, ACallB) {
657 // Any url can load a.
658 AddLoaderForURL(GURL(kTestAURLString), std::string());
659
660 // Only a can load b.
661 AddLoaderForURL(GURL(kTestBURLString), kTestAURLString);
662
663 TestAPtr a;
664 application_manager_->ConnectToService(GURL(kTestAURLString), &a);
665 a->CallB();
666 loop_.Run();
667 EXPECT_EQ(1, tester_context_.num_b_calls());
668 EXPECT_TRUE(tester_context_.a_called_quit());
669}
670
James Robinson646469d2014-10-03 15:33:28 -0700671// Confirm that a service impl will be deleted if the app that connected to
672// it goes away.
673TEST_F(ApplicationManagerTest, BDeleted) {
674 AddLoaderForURL(GURL(kTestAURLString), std::string());
675 AddLoaderForURL(GURL(kTestBURLString), std::string());
676
677 TestAPtr a;
678 application_manager_->ConnectToService(GURL(kTestAURLString), &a);
679
680 a->CallB();
681 loop_.Run();
682
683 // Kills the a app.
684 application_manager_->SetLoaderForURL(scoped_ptr<ApplicationLoader>(),
685 GURL(kTestAURLString));
686 loop_.Run();
687
688 EXPECT_EQ(1, tester_context_.num_b_deletes());
689}
690
691// Confirm that the url of a service is correctly passed to another service that
692// it loads, and that it can be rejected.
693TEST_F(ApplicationManagerTest, ANoLoadB) {
694 // Any url can load a.
695 AddLoaderForURL(GURL(kTestAURLString), std::string());
696
697 // Only c can load b, so this will fail.
698 AddLoaderForURL(GURL(kTestBURLString), "test:TestC");
699
700 TestAPtr a;
701 application_manager_->ConnectToService(GURL(kTestAURLString), &a);
702 a->CallB();
703 loop_.Run();
704 EXPECT_EQ(0, tester_context_.num_b_calls());
705
706 EXPECT_FALSE(tester_context_.a_called_quit());
707 EXPECT_TRUE(tester_context_.tester_called_quit());
708}
709
710TEST_F(ApplicationManagerTest, NoServiceNoLoad) {
711 AddLoaderForURL(GURL(kTestAURLString), std::string());
712
713 // There is no TestC service implementation registered with
714 // ApplicationManager, so this cannot succeed (but also shouldn't crash).
715 TestCPtr c;
716 application_manager_->ConnectToService(GURL(kTestAURLString), &c);
Viet-Trung Luu01e64cf2015-07-08 09:55:53 -0700717 c.set_connection_error_handler(
718 []() { base::MessageLoop::current()->QuitWhenIdle(); });
James Robinson646469d2014-10-03 15:33:28 -0700719
720 loop_.Run();
721 EXPECT_TRUE(c.encountered_error());
722}
723
Aaron Boodmancd7b9112014-11-06 21:44:49 -0800724TEST_F(ApplicationManagerTest, MappedURLsShouldNotCauseDuplicateLoad) {
725 test_delegate_.AddMapping(GURL("foo:foo2"), GURL("foo:foo"));
726 // 1 because ApplicationManagerTest connects once at startup.
727 EXPECT_EQ(1, test_loader_->num_loads());
728
729 TestServicePtr test_service;
730 application_manager_->ConnectToService(GURL("foo:foo"), &test_service);
731 EXPECT_EQ(2, test_loader_->num_loads());
732
733 TestServicePtr test_service2;
734 application_manager_->ConnectToService(GURL("foo:foo2"), &test_service2);
735 EXPECT_EQ(2, test_loader_->num_loads());
736
737 TestServicePtr test_service3;
738 application_manager_->ConnectToService(GURL("bar:bar"), &test_service2);
739 EXPECT_EQ(3, test_loader_->num_loads());
740}
741
Benjamin Lerman75aef1d2015-01-21 12:04:39 +0100742TEST_F(ApplicationManagerTest, MappedURLsShouldWorkWithLoaders) {
743 TestApplicationLoader* custom_loader = new TestApplicationLoader;
744 TestContext context;
745 custom_loader->set_context(&context);
746 application_manager_->SetLoaderForURL(make_scoped_ptr(custom_loader),
747 GURL("mojo:foo"));
748 test_delegate_.AddMapping(GURL("mojo:foo2"), GURL("mojo:foo"));
749
750 TestServicePtr test_service;
751 application_manager_->ConnectToService(GURL("mojo:foo2"), &test_service);
752 EXPECT_EQ(1, custom_loader->num_loads());
753 custom_loader->set_context(nullptr);
754}
755
Benjamin Lermanc76642f2015-03-04 15:00:55 +0100756TEST_F(ApplicationManagerTest, TestQueryWithLoaders) {
757 TestApplicationLoader* url_loader = new TestApplicationLoader;
758 TestApplicationLoader* scheme_loader = new TestApplicationLoader;
759 application_manager_->SetLoaderForURL(
760 scoped_ptr<ApplicationLoader>(url_loader), GURL("test:test1"));
761 application_manager_->SetLoaderForScheme(
762 scoped_ptr<ApplicationLoader>(scheme_loader), "test");
763
764 // test::test1 should go to url_loader.
765 TestServicePtr test_service;
766 application_manager_->ConnectToService(GURL("test:test1?foo=bar"),
767 &test_service);
768 EXPECT_EQ(1, url_loader->num_loads());
769 EXPECT_EQ(0, scheme_loader->num_loads());
770
771 // test::test2 should go to scheme loader.
772 application_manager_->ConnectToService(GURL("test:test2?foo=bar"),
773 &test_service);
774 EXPECT_EQ(1, url_loader->num_loads());
775 EXPECT_EQ(1, scheme_loader->num_loads());
776}
777
Benjamin Lerman993869e2015-03-24 13:35:28 +0100778TEST_F(ApplicationManagerTest, TestEndApplicationClosure) {
779 ClosingApplicationLoader* loader = new ClosingApplicationLoader();
780 application_manager_->SetLoaderForScheme(
781 scoped_ptr<ApplicationLoader>(loader), "test");
782
783 bool called = false;
784 application_manager_->ConnectToApplication(
Viet-Trung Luud588c942016-05-09 16:49:45 -0700785 GURL("test:test"), GURL(), nullptr,
Benjamin Lerman993869e2015-03-24 13:35:28 +0100786 base::Bind(&QuitClosure, base::Unretained(&called)));
787 loop_.Run();
788 EXPECT_TRUE(called);
789}
790
Viet-Trung Luu36faa4d2015-03-04 18:08:18 -0800791} // namespace
792} // namespace shell