blob: 39e731d647054a87b0c359e14d86374a4ec4b5f9 [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"
Viet-Trung Luu73e948c2016-05-31 16:42:43 -070014#include "mojo/public/cpp/application/application_impl_base.h"
Viet-Trung Luu7ab22132016-04-26 21:09:03 -070015#include "mojo/public/cpp/application/connect.h"
Viet-Trung Luub237bca2016-05-13 16:35:11 -070016#include "mojo/public/cpp/application/service_provider_impl.h"
Dave Moore2abdce52015-01-26 15:41:12 -080017#include "mojo/public/cpp/bindings/strong_binding.h"
James Robinson646469d2014-10-03 15:33:28 -070018#include "mojo/public/interfaces/application/service_provider.mojom.h"
Przemysław Pietrzkiewicz6384d092015-01-15 16:03:17 -080019#include "shell/application_manager/application_loader.h"
Przemysław Pietrzkiewicz6384d092015-01-15 16:03:17 -080020#include "shell/application_manager/test.mojom.h"
James Robinson646469d2014-10-03 15:33:28 -070021#include "testing/gtest/include/gtest/gtest.h"
22
Viet-Trung Luue377a9e2015-04-09 13:53:21 -070023using mojo::Application;
Viet-Trung Luu73e948c2016-05-31 16:42:43 -070024using mojo::ApplicationImplBase;
Viet-Trung Luue377a9e2015-04-09 13:53:21 -070025using mojo::Callback;
Viet-Trung Luud21f93b2016-05-12 16:35:38 -070026using mojo::ConnectionContext;
Viet-Trung Luue377a9e2015-04-09 13:53:21 -070027using mojo::InterfaceRequest;
Viet-Trung Luu73e948c2016-05-31 16:42:43 -070028using mojo::ServiceProviderImpl;
Viet-Trung Luue377a9e2015-04-09 13:53:21 -070029using mojo::StrongBinding;
30
Viet-Trung Luu36faa4d2015-03-04 18:08:18 -080031namespace shell {
James Robinson646469d2014-10-03 15:33:28 -070032namespace {
33
34const char kTestURLString[] = "test:testService";
35const char kTestAURLString[] = "test:TestA";
36const char kTestBURLString[] = "test:TestB";
37
38struct TestContext {
39 TestContext() : num_impls(0), num_loader_deletes(0) {}
40 std::string last_test_string;
41 int num_impls;
42 int num_loader_deletes;
43};
44
Benjamin Lerman993869e2015-03-24 13:35:28 +010045void QuitClosure(bool* value) {
46 *value = true;
47 base::MessageLoop::current()->QuitWhenIdle();
48}
49
Dave Moore2abdce52015-01-26 15:41:12 -080050class TestServiceImpl : public TestService {
James Robinson646469d2014-10-03 15:33:28 -070051 public:
Viet-Trung Luue377a9e2015-04-09 13:53:21 -070052 TestServiceImpl(TestContext* context, InterfaceRequest<TestService> request)
Dave Moore2abdce52015-01-26 15:41:12 -080053 : context_(context), binding_(this, request.Pass()) {
James Robinson646469d2014-10-03 15:33:28 -070054 ++context_->num_impls;
55 }
56
Dave Moore2abdce52015-01-26 15:41:12 -080057 ~TestServiceImpl() override {
58 --context_->num_impls;
James Robinson646469d2014-10-03 15:33:28 -070059 if (!base::MessageLoop::current()->is_running())
60 return;
61 base::MessageLoop::current()->Quit();
62 }
63
64 // TestService implementation:
Viet-Trung Luubd07e3a2015-04-09 12:43:29 -070065 void Test(const mojo::String& test_string,
Viet-Trung Luue377a9e2015-04-09 13:53:21 -070066 const Callback<void()>& callback) override {
James Robinson646469d2014-10-03 15:33:28 -070067 context_->last_test_string = test_string;
Aaron Boodman8b78ea32015-01-21 09:28:10 -080068 callback.Run();
James Robinson646469d2014-10-03 15:33:28 -070069 }
70
71 private:
72 TestContext* context_;
Viet-Trung Luue377a9e2015-04-09 13:53:21 -070073 StrongBinding<TestService> binding_;
James Robinson646469d2014-10-03 15:33:28 -070074};
75
Aaron Boodman8b78ea32015-01-21 09:28:10 -080076class TestClient {
James Robinson646469d2014-10-03 15:33:28 -070077 public:
Aaron Boodman8b78ea32015-01-21 09:28:10 -080078 explicit TestClient(TestServicePtr service)
79 : service_(service.Pass()), quit_after_ack_(false) {}
James Robinson646469d2014-10-03 15:33:28 -070080
Aaron Boodman8b78ea32015-01-21 09:28:10 -080081 void AckTest() {
James Robinson646469d2014-10-03 15:33:28 -070082 if (quit_after_ack_)
83 base::MessageLoop::current()->Quit();
84 }
85
Scott Violetdd035f52014-12-18 08:47:12 -080086 void Test(const std::string& test_string) {
James Robinson646469d2014-10-03 15:33:28 -070087 quit_after_ack_ = true;
Aaron Boodman8b78ea32015-01-21 09:28:10 -080088 service_->Test(test_string,
89 base::Bind(&TestClient::AckTest, base::Unretained(this)));
James Robinson646469d2014-10-03 15:33:28 -070090 }
91
92 private:
93 TestServicePtr service_;
94 bool quit_after_ack_;
Aaron Boodman8b78ea32015-01-21 09:28:10 -080095 DISALLOW_COPY_AND_ASSIGN(TestClient);
James Robinson646469d2014-10-03 15:33:28 -070096};
97
98class TestApplicationLoader : public ApplicationLoader,
Viet-Trung Luu73e948c2016-05-31 16:42:43 -070099 public ApplicationImplBase {
James Robinson646469d2014-10-03 15:33:28 -0700100 public:
Viet-Trung Luua417b142015-03-31 11:24:44 -0700101 TestApplicationLoader() : context_(nullptr), num_loads_(0) {}
James Robinson646469d2014-10-03 15:33:28 -0700102
James Robinsone1b30cf2014-10-21 12:25:40 -0700103 ~TestApplicationLoader() override {
James Robinson646469d2014-10-03 15:33:28 -0700104 if (context_)
105 ++context_->num_loader_deletes;
James Robinson646469d2014-10-03 15:33:28 -0700106 }
107
108 void set_context(TestContext* context) { context_ = context; }
109 int num_loads() const { return num_loads_; }
James Robinson646469d2014-10-03 15:33:28 -0700110
111 private:
112 // ApplicationLoader implementation.
Viet-Trung Luue377a9e2015-04-09 13:53:21 -0700113 void Load(const GURL& url,
114 InterfaceRequest<Application> application_request) override {
James Robinson646469d2014-10-03 15:33:28 -0700115 ++num_loads_;
Viet-Trung Luu73e948c2016-05-31 16:42:43 -0700116 if (application_binding().is_bound())
117 application_binding().Close();
118 Bind(application_request.Pass());
James Robinson646469d2014-10-03 15:33:28 -0700119 }
120
Viet-Trung Luu73e948c2016-05-31 16:42:43 -0700121 // ApplicationImplBase override.
122 bool OnAcceptConnection(ServiceProviderImpl* service_provider_impl) override {
Viet-Trung Luu22e78b32016-05-13 15:27:15 -0700123 service_provider_impl->AddService<TestService>(
Viet-Trung Luu5e30a072016-05-13 14:12:59 -0700124 [this](const ConnectionContext& connection_context,
125 InterfaceRequest<TestService> request) {
126 new TestServiceImpl(context_, request.Pass());
127 });
James Robinson646469d2014-10-03 15:33:28 -0700128 return true;
129 }
130
James Robinson646469d2014-10-03 15:33:28 -0700131 TestContext* context_;
132 int num_loads_;
133 DISALLOW_COPY_AND_ASSIGN(TestApplicationLoader);
134};
135
Benjamin Lerman993869e2015-03-24 13:35:28 +0100136class ClosingApplicationLoader : public ApplicationLoader {
137 private:
138 // ApplicationLoader implementation.
Viet-Trung Luue377a9e2015-04-09 13:53:21 -0700139 void Load(const GURL& url,
140 InterfaceRequest<Application> application_request) override {}
Benjamin Lerman993869e2015-03-24 13:35:28 +0100141};
142
James Robinson646469d2014-10-03 15:33:28 -0700143class 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.
Scott Violetdd035f52014-12-18 08:47:12 -0800239class TestAImpl : public TestA {
James Robinson646469d2014-10-03 15:33:28 -0700240 public:
Viet-Trung Luu7ab22132016-04-26 21:09:03 -0700241 TestAImpl(mojo::InterfaceHandle<mojo::ServiceProvider> b_sp_handle,
Scott Violetdd035f52014-12-18 08:47:12 -0800242 TesterContext* test_context,
Viet-Trung Luue377a9e2015-04-09 13:53:21 -0700243 InterfaceRequest<TestA> request)
Geoffrey Gowan8e12b962015-02-09 16:45:05 -0800244 : test_context_(test_context), binding_(this, request.Pass()) {
Viet-Trung Luu7ab22132016-04-26 21:09:03 -0700245 auto b_sp = mojo::ServiceProviderPtr::Create(b_sp_handle.Pass());
246 mojo::ConnectToService(b_sp.get(), GetProxy(&b_));
James Robinson646469d2014-10-03 15:33:28 -0700247 }
Dave Moore2abdce52015-01-26 15:41:12 -0800248
James Robinsone1b30cf2014-10-21 12:25:40 -0700249 ~TestAImpl() override {
James Robinson646469d2014-10-03 15:33:28 -0700250 test_context_->IncrementNumADeletes();
251 if (base::MessageLoop::current()->is_running())
252 Quit();
253 }
254
255 private:
James Robinsone1b30cf2014-10-21 12:25:40 -0700256 void CallB() override {
James Robinson646469d2014-10-03 15:33:28 -0700257 b_->B(base::Bind(&TestAImpl::Quit, base::Unretained(this)));
258 }
259
James Robinson646469d2014-10-03 15:33:28 -0700260 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_;
Viet-Trung Luue377a9e2015-04-09 13:53:21 -0700268 StrongBinding<TestA> binding_;
James Robinson646469d2014-10-03 15:33:28 -0700269};
270
Dave Moore2abdce52015-01-26 15:41:12 -0800271class TestBImpl : public TestB {
James Robinson646469d2014-10-03 15:33:28 -0700272 public:
Viet-Trung Luud21f93b2016-05-12 16:35:38 -0700273 TestBImpl(TesterContext* test_context, InterfaceRequest<TestB> request)
Viet-Trung Luu7f38d692016-05-09 12:53:14 -0700274 : test_context_(test_context), binding_(this, request.Pass()) {}
James Robinson646469d2014-10-03 15:33:28 -0700275
James Robinsone1b30cf2014-10-21 12:25:40 -0700276 ~TestBImpl() override {
James Robinson646469d2014-10-03 15:33:28 -0700277 test_context_->IncrementNumBDeletes();
278 if (base::MessageLoop::current()->is_running())
279 base::MessageLoop::current()->Quit();
280 test_context_->QuitSoon();
281 }
282
283 private:
Viet-Trung Luue377a9e2015-04-09 13:53:21 -0700284 void B(const Callback<void()>& callback) override {
James Robinson646469d2014-10-03 15:33:28 -0700285 test_context_->IncrementNumBCalls();
286 callback.Run();
287 }
288
James Robinson646469d2014-10-03 15:33:28 -0700289 TesterContext* test_context_;
Viet-Trung Luue377a9e2015-04-09 13:53:21 -0700290 StrongBinding<TestB> binding_;
James Robinson646469d2014-10-03 15:33:28 -0700291};
292
Viet-Trung Luu73e948c2016-05-31 16:42:43 -0700293class Tester : public ApplicationImplBase, public ApplicationLoader {
James Robinson646469d2014-10-03 15:33:28 -0700294 public:
295 Tester(TesterContext* context, const std::string& requestor_url)
296 : context_(context), requestor_url_(requestor_url) {}
James Robinsone1b30cf2014-10-21 12:25:40 -0700297 ~Tester() override {}
James Robinson646469d2014-10-03 15:33:28 -0700298
299 private:
Viet-Trung Luue377a9e2015-04-09 13:53:21 -0700300 void Load(const GURL& url,
301 InterfaceRequest<Application> application_request) override {
Viet-Trung Luu73e948c2016-05-31 16:42:43 -0700302 Bind(application_request.Pass());
James Robinson646469d2014-10-03 15:33:28 -0700303 }
304
Viet-Trung Luu73e948c2016-05-31 16:42:43 -0700305 bool OnAcceptConnection(ServiceProviderImpl* service_provider_impl) override {
Viet-Trung Luu087fc162016-05-13 11:15:55 -0700306 const std::string& remote_url =
Viet-Trung Luu22e78b32016-05-13 15:27:15 -0700307 service_provider_impl->connection_context().remote_url;
Viet-Trung Luu087fc162016-05-13 11:15:55 -0700308 if (!requestor_url_.empty() && requestor_url_ != remote_url) {
James Robinson646469d2014-10-03 15:33:28 -0700309 context_->set_tester_called_quit();
310 context_->QuitSoon();
311 base::MessageLoop::current()->Quit();
312 return false;
313 }
314 // If we're coming from A, then add B, otherwise A.
Viet-Trung Luu5e30a072016-05-13 14:12:59 -0700315 if (remote_url == kTestAURLString) {
Viet-Trung Luu22e78b32016-05-13 15:27:15 -0700316 service_provider_impl->AddService<TestB>(
Viet-Trung Luu5e30a072016-05-13 14:12:59 -0700317 [this](const ConnectionContext& connection_context,
318 InterfaceRequest<TestB> test_b_request) {
319 new TestBImpl(context_, test_b_request.Pass());
320 });
321 } else {
Viet-Trung Luu22e78b32016-05-13 15:27:15 -0700322 service_provider_impl->AddService<TestA>(
Viet-Trung Luu5e30a072016-05-13 14:12:59 -0700323 [this](const ConnectionContext& connection_context,
324 InterfaceRequest<TestA> test_a_request) {
325 mojo::InterfaceHandle<mojo::ServiceProvider> incoming_sp_handle;
Viet-Trung Luu568f8452016-06-06 14:25:33 -0700326 shell()->ConnectToApplication(kTestBURLString,
327 GetProxy(&incoming_sp_handle));
Viet-Trung Luu5e30a072016-05-13 14:12:59 -0700328 a_bindings_.push_back(new TestAImpl(
329 incoming_sp_handle.Pass(), context_, test_a_request.Pass()));
330 });
331 }
James Robinson646469d2014-10-03 15:33:28 -0700332 return true;
333 }
334
James Robinson646469d2014-10-03 15:33:28 -0700335 TesterContext* context_;
James Robinson646469d2014-10-03 15:33:28 -0700336 std::string requestor_url_;
Scott Violetdd035f52014-12-18 08:47:12 -0800337 ScopedVector<TestAImpl> a_bindings_;
James Robinson646469d2014-10-03 15:33:28 -0700338};
339
Aaron Boodmancd7b9112014-11-06 21:44:49 -0800340class TestDelegate : public ApplicationManager::Delegate {
341 public:
Viet-Trung Luu32952272015-02-11 16:32:03 -0800342 void AddMapping(const GURL& from, const GURL& to) { mappings_[from] = to; }
Aaron Boodmancd7b9112014-11-06 21:44:49 -0800343
344 // ApplicationManager::Delegate
Viet-Trung Luu32952272015-02-11 16:32:03 -0800345 GURL ResolveMappings(const GURL& url) override {
Aaron Boodmancd7b9112014-11-06 21:44:49 -0800346 auto it = mappings_.find(url);
347 if (it != mappings_.end())
348 return it->second;
349 return url;
350 }
Benjamin Lerman605969e2015-04-30 13:51:04 +0200351 GURL ResolveMojoURL(const GURL& url) override {
Benjamin Lerman75aef1d2015-01-21 12:04:39 +0100352 GURL mapped_url = ResolveMappings(url);
353 // The shell automatically map mojo URLs.
354 if (mapped_url.scheme() == "mojo") {
355 url::Replacements<char> replacements;
356 replacements.SetScheme("file", url::Component(0, 4));
357 mapped_url = mapped_url.ReplaceComponents(replacements);
358 }
359 return mapped_url;
360 }
361
Aaron Boodmancd7b9112014-11-06 21:44:49 -0800362 private:
363 std::map<GURL, GURL> mappings_;
364};
365
Viet-Trung Luu73e948c2016-05-31 16:42:43 -0700366class TestExternal : public ApplicationImplBase {
Dave Moore0504d062015-01-23 15:33:29 -0800367 public:
Dave Mooref2efe552015-01-26 14:31:45 -0800368 TestExternal() : configure_incoming_connection_called_(false) {}
Dave Moore0504d062015-01-23 15:33:29 -0800369
Viet-Trung Luu73e948c2016-05-31 16:42:43 -0700370 void OnInitialize() override { base::MessageLoop::current()->Quit(); }
Dave Moore0504d062015-01-23 15:33:29 -0800371
Viet-Trung Luu73e948c2016-05-31 16:42:43 -0700372 bool OnAcceptConnection(ServiceProviderImpl* service_provider_impl) override {
Dave Moore0504d062015-01-23 15:33:29 -0800373 configure_incoming_connection_called_ = true;
374 base::MessageLoop::current()->Quit();
375 return true;
376 }
377
Viet-Trung Luu73e948c2016-05-31 16:42:43 -0700378 const std::vector<std::string>& initialize_args() const { return args(); }
Dave Mooref2efe552015-01-26 14:31:45 -0800379
Dave Moore0504d062015-01-23 15:33:29 -0800380 bool configure_incoming_connection_called() const {
381 return configure_incoming_connection_called_;
382 }
383
384 private:
Dave Moore0504d062015-01-23 15:33:29 -0800385 bool configure_incoming_connection_called_;
386};
387
James Robinson646469d2014-10-03 15:33:28 -0700388class ApplicationManagerTest : public testing::Test {
389 public:
390 ApplicationManagerTest() : tester_context_(&loop_) {}
391
Viet-Trung Luu153dd212014-10-21 14:41:15 -0700392 ~ApplicationManagerTest() override {}
James Robinson646469d2014-10-03 15:33:28 -0700393
Viet-Trung Luu153dd212014-10-21 14:41:15 -0700394 void SetUp() override {
Viet-Trung Luu988b4be2015-05-15 13:00:15 -0700395 application_manager_.reset(
396 new ApplicationManager(ApplicationManager::Options(), &test_delegate_));
Aaron Boodmancd7b9112014-11-06 21:44:49 -0800397 test_loader_ = new TestApplicationLoader;
398 test_loader_->set_context(&context_);
James Robinson646469d2014-10-03 15:33:28 -0700399 application_manager_->set_default_loader(
Aaron Boodmancd7b9112014-11-06 21:44:49 -0800400 scoped_ptr<ApplicationLoader>(test_loader_));
James Robinson646469d2014-10-03 15:33:28 -0700401
402 TestServicePtr service_proxy;
403 application_manager_->ConnectToService(GURL(kTestURLString),
404 &service_proxy);
Aaron Boodman8b78ea32015-01-21 09:28:10 -0800405 test_client_.reset(new TestClient(service_proxy.Pass()));
James Robinson646469d2014-10-03 15:33:28 -0700406 }
407
Viet-Trung Luu153dd212014-10-21 14:41:15 -0700408 void TearDown() override {
Viet-Trung Luua417b142015-03-31 11:24:44 -0700409 test_client_.reset();
410 application_manager_.reset();
James Robinson646469d2014-10-03 15:33:28 -0700411 }
412
James Robinson646469d2014-10-03 15:33:28 -0700413 void AddLoaderForURL(const GURL& url, const std::string& requestor_url) {
Scott Violetdd035f52014-12-18 08:47:12 -0800414 application_manager_->SetLoaderForURL(
415 make_scoped_ptr(new Tester(&tester_context_, requestor_url)), url);
James Robinson646469d2014-10-03 15:33:28 -0700416 }
417
418 bool HasFactoryForTestURL() {
419 ApplicationManager::TestAPI manager_test_api(application_manager_.get());
420 return manager_test_api.HasFactoryForURL(GURL(kTestURLString));
421 }
422
423 protected:
424 base::ShadowingAtExitManager at_exit_;
Aaron Boodmancd7b9112014-11-06 21:44:49 -0800425 TestDelegate test_delegate_;
426 TestApplicationLoader* test_loader_;
James Robinson646469d2014-10-03 15:33:28 -0700427 TesterContext tester_context_;
428 TestContext context_;
429 base::MessageLoop loop_;
Aaron Boodman8b78ea32015-01-21 09:28:10 -0800430 scoped_ptr<TestClient> test_client_;
James Robinson646469d2014-10-03 15:33:28 -0700431 scoped_ptr<ApplicationManager> application_manager_;
432 DISALLOW_COPY_AND_ASSIGN(ApplicationManagerTest);
433};
434
435TEST_F(ApplicationManagerTest, Basic) {
436 test_client_->Test("test");
437 loop_.Run();
438 EXPECT_EQ(std::string("test"), context_.last_test_string);
439}
440
441// Confirm that no arguments are sent to an application by default.
442TEST_F(ApplicationManagerTest, NoArgs) {
Viet-Trung Luu988b4be2015-05-15 13:00:15 -0700443 ApplicationManager am(ApplicationManager::Options(), &test_delegate_);
James Robinson646469d2014-10-03 15:33:28 -0700444 GURL test_url("test:test");
James Robinson646469d2014-10-03 15:33:28 -0700445 TestApplicationLoader* loader = new TestApplicationLoader;
Scott Violetba1f42c2014-12-04 11:08:49 -0800446 loader->set_context(&context_);
James Robinson646469d2014-10-03 15:33:28 -0700447 am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(loader), test_url);
448 TestServicePtr test_service;
449 am.ConnectToService(test_url, &test_service);
Aaron Boodman8b78ea32015-01-21 09:28:10 -0800450 TestClient test_client(test_service.Pass());
James Robinson646469d2014-10-03 15:33:28 -0700451 test_client.Test("test");
452 loop_.Run();
Viet-Trung Luu73e948c2016-05-31 16:42:43 -0700453 std::vector<std::string> app_args = loader->args();
James Robinson646469d2014-10-03 15:33:28 -0700454 EXPECT_EQ(0U, app_args.size());
455}
456
457// Confirm that arguments are sent to an application.
458TEST_F(ApplicationManagerTest, Args) {
Viet-Trung Luu988b4be2015-05-15 13:00:15 -0700459 ApplicationManager am(ApplicationManager::Options(), &test_delegate_);
James Robinson646469d2014-10-03 15:33:28 -0700460 GURL test_url("test:test");
461 std::vector<std::string> args;
462 args.push_back("test_arg1");
463 args.push_back("test_arg2");
464 am.SetArgsForURL(args, test_url);
James Robinson646469d2014-10-03 15:33:28 -0700465 TestApplicationLoader* loader = new TestApplicationLoader;
Scott Violetba1f42c2014-12-04 11:08:49 -0800466 loader->set_context(&context_);
James Robinson646469d2014-10-03 15:33:28 -0700467 am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(loader), test_url);
468 TestServicePtr test_service;
469 am.ConnectToService(test_url, &test_service);
Aaron Boodman8b78ea32015-01-21 09:28:10 -0800470 TestClient test_client(test_service.Pass());
James Robinson646469d2014-10-03 15:33:28 -0700471 test_client.Test("test");
472 loop_.Run();
Viet-Trung Luu73e948c2016-05-31 16:42:43 -0700473 std::vector<std::string> app_args = loader->args();
Benjamin Lermanf3b7f562015-11-23 18:18:03 +0100474 ASSERT_EQ(args.size() + 1, app_args.size());
475 EXPECT_EQ(args[0], app_args[1]);
476 EXPECT_EQ(args[1], app_args[2]);
James Robinson646469d2014-10-03 15:33:28 -0700477}
478
Benjamin Lermanaec7ef82015-11-23 15:34:06 +0100479// Confirm that arguments are sent to an application in the presence of query
480// parameters.
481TEST_F(ApplicationManagerTest, ArgsWithQuery) {
482 ApplicationManager am(ApplicationManager::Options(), &test_delegate_);
483 GURL test_url("test:test");
484 GURL test_url_with_query("test:test?foo=bar");
485 std::vector<std::string> args;
486 args.push_back("test_arg1");
487 am.SetArgsForURL(args, test_url);
488 TestApplicationLoader* loader = new TestApplicationLoader;
489 loader->set_context(&context_);
490 am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(loader), test_url);
491 TestServicePtr test_service;
492 am.ConnectToService(test_url_with_query, &test_service);
493 TestClient test_client(test_service.Pass());
494 test_client.Test("test");
495 loop_.Run();
Viet-Trung Luu73e948c2016-05-31 16:42:43 -0700496 std::vector<std::string> app_args = loader->args();
Benjamin Lermanf3b7f562015-11-23 18:18:03 +0100497 ASSERT_EQ(args.size() + 1, app_args.size());
498 EXPECT_EQ(args[0], app_args[1]);
499}
500
501// Confirm that the URL is not duplicated when arguments are added in multiple
502// phases.
503TEST_F(ApplicationManagerTest, ArgsMultipleCalls) {
504 ApplicationManager am(ApplicationManager::Options(), &test_delegate_);
505 GURL test_url("test:test");
506 std::vector<std::string> args1;
507 args1.push_back("test_arg1");
508 am.SetArgsForURL(args1, test_url);
509 std::vector<std::string> args2;
510 args2.push_back("test_arg2");
511 am.SetArgsForURL(args2, test_url);
512 TestApplicationLoader* loader = new TestApplicationLoader;
513 loader->set_context(&context_);
514 am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(loader), test_url);
515 TestServicePtr test_service;
516 am.ConnectToService(test_url, &test_service);
517 TestClient test_client(test_service.Pass());
518 test_client.Test("test");
519 loop_.Run();
Viet-Trung Luu73e948c2016-05-31 16:42:43 -0700520 std::vector<std::string> app_args = loader->args();
Benjamin Lermanf3b7f562015-11-23 18:18:03 +0100521 ASSERT_EQ(args1.size() + args2.size() + 1, app_args.size());
522 EXPECT_EQ(args1[0], app_args[1]);
523 EXPECT_EQ(args2[0], app_args[2]);
Benjamin Lermanaec7ef82015-11-23 15:34:06 +0100524}
525
Benjamin Lermanacf32fb2015-03-24 10:54:37 +0100526// Confirm that arguments are aggregated through mappings.
527TEST_F(ApplicationManagerTest, ArgsAndMapping) {
Viet-Trung Luu988b4be2015-05-15 13:00:15 -0700528 ApplicationManager am(ApplicationManager::Options(), &test_delegate_);
Benjamin Lermanacf32fb2015-03-24 10:54:37 +0100529 GURL test_url("test:test");
530 GURL test_url2("test:test2");
531 test_delegate_.AddMapping(test_url, test_url2);
532 std::vector<std::string> args;
533 args.push_back("test_arg1");
534 args.push_back("test_arg2");
535 am.SetArgsForURL(args, test_url);
536 std::vector<std::string> args2;
537 args2.push_back("test_arg3");
538 args2.push_back("test_arg4");
539 am.SetArgsForURL(args2, test_url2);
540 TestApplicationLoader* loader = new TestApplicationLoader;
541 loader->set_context(&context_);
542 am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(loader), test_url2);
543 {
544 // Connext to the mapped url
545 TestServicePtr test_service;
546 am.ConnectToService(test_url, &test_service);
547 TestClient test_client(test_service.Pass());
548 test_client.Test("test");
549 loop_.Run();
Viet-Trung Luu73e948c2016-05-31 16:42:43 -0700550 std::vector<std::string> app_args = loader->args();
Benjamin Lermanf3b7f562015-11-23 18:18:03 +0100551 ASSERT_EQ(args.size() + args2.size() + 1, app_args.size());
552 EXPECT_EQ(args[0], app_args[1]);
553 EXPECT_EQ(args[1], app_args[2]);
554 EXPECT_EQ(args2[0], app_args[3]);
555 EXPECT_EQ(args2[1], app_args[4]);
Benjamin Lermanacf32fb2015-03-24 10:54:37 +0100556 }
557 {
558 // Connext to the target url
559 TestServicePtr test_service;
560 am.ConnectToService(test_url2, &test_service);
561 TestClient test_client(test_service.Pass());
562 test_client.Test("test");
563 loop_.Run();
Viet-Trung Luu73e948c2016-05-31 16:42:43 -0700564 std::vector<std::string> app_args = loader->args();
Benjamin Lermanf3b7f562015-11-23 18:18:03 +0100565 ASSERT_EQ(args.size() + args2.size() + 1, app_args.size());
566 EXPECT_EQ(args[0], app_args[1]);
567 EXPECT_EQ(args[1], app_args[2]);
568 EXPECT_EQ(args2[0], app_args[3]);
569 EXPECT_EQ(args2[1], app_args[4]);
Benjamin Lermanacf32fb2015-03-24 10:54:37 +0100570 }
571}
572
James Robinson646469d2014-10-03 15:33:28 -0700573TEST_F(ApplicationManagerTest, ClientError) {
574 test_client_->Test("test");
575 EXPECT_TRUE(HasFactoryForTestURL());
576 loop_.Run();
577 EXPECT_EQ(1, context_.num_impls);
Viet-Trung Luua417b142015-03-31 11:24:44 -0700578 test_client_.reset();
James Robinson646469d2014-10-03 15:33:28 -0700579 loop_.Run();
580 EXPECT_EQ(0, context_.num_impls);
581 EXPECT_TRUE(HasFactoryForTestURL());
582}
583
584TEST_F(ApplicationManagerTest, Deletes) {
585 {
Viet-Trung Luu988b4be2015-05-15 13:00:15 -0700586 ApplicationManager am(ApplicationManager::Options(), &test_delegate_);
James Robinson646469d2014-10-03 15:33:28 -0700587 TestApplicationLoader* default_loader = new TestApplicationLoader;
588 default_loader->set_context(&context_);
589 TestApplicationLoader* url_loader1 = new TestApplicationLoader;
590 TestApplicationLoader* url_loader2 = new TestApplicationLoader;
591 url_loader1->set_context(&context_);
592 url_loader2->set_context(&context_);
593 TestApplicationLoader* scheme_loader1 = new TestApplicationLoader;
594 TestApplicationLoader* scheme_loader2 = new TestApplicationLoader;
595 scheme_loader1->set_context(&context_);
596 scheme_loader2->set_context(&context_);
597 am.set_default_loader(scoped_ptr<ApplicationLoader>(default_loader));
598 am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(url_loader1),
599 GURL("test:test1"));
600 am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(url_loader2),
601 GURL("test:test1"));
602 am.SetLoaderForScheme(scoped_ptr<ApplicationLoader>(scheme_loader1),
603 "test");
604 am.SetLoaderForScheme(scoped_ptr<ApplicationLoader>(scheme_loader2),
605 "test");
606 }
607 EXPECT_EQ(5, context_.num_loader_deletes);
608}
609
610// Confirm that both urls and schemes can have their loaders explicitly set.
611TEST_F(ApplicationManagerTest, SetLoaders) {
612 TestApplicationLoader* default_loader = new TestApplicationLoader;
613 TestApplicationLoader* url_loader = new TestApplicationLoader;
614 TestApplicationLoader* scheme_loader = new TestApplicationLoader;
615 application_manager_->set_default_loader(
616 scoped_ptr<ApplicationLoader>(default_loader));
617 application_manager_->SetLoaderForURL(
618 scoped_ptr<ApplicationLoader>(url_loader), GURL("test:test1"));
619 application_manager_->SetLoaderForScheme(
620 scoped_ptr<ApplicationLoader>(scheme_loader), "test");
621
622 // test::test1 should go to url_loader.
623 TestServicePtr test_service;
624 application_manager_->ConnectToService(GURL("test:test1"), &test_service);
625 EXPECT_EQ(1, url_loader->num_loads());
626 EXPECT_EQ(0, scheme_loader->num_loads());
627 EXPECT_EQ(0, default_loader->num_loads());
628
629 // test::test2 should go to scheme loader.
630 application_manager_->ConnectToService(GURL("test:test2"), &test_service);
631 EXPECT_EQ(1, url_loader->num_loads());
632 EXPECT_EQ(1, scheme_loader->num_loads());
633 EXPECT_EQ(0, default_loader->num_loads());
634
635 // http::test1 should go to default loader.
636 application_manager_->ConnectToService(GURL("http:test1"), &test_service);
637 EXPECT_EQ(1, url_loader->num_loads());
638 EXPECT_EQ(1, scheme_loader->num_loads());
639 EXPECT_EQ(1, default_loader->num_loads());
640}
641
642// Confirm that the url of a service is correctly passed to another service that
643// it loads.
644TEST_F(ApplicationManagerTest, ACallB) {
645 // Any url can load a.
646 AddLoaderForURL(GURL(kTestAURLString), std::string());
647
648 // Only a can load b.
649 AddLoaderForURL(GURL(kTestBURLString), kTestAURLString);
650
651 TestAPtr a;
652 application_manager_->ConnectToService(GURL(kTestAURLString), &a);
653 a->CallB();
654 loop_.Run();
655 EXPECT_EQ(1, tester_context_.num_b_calls());
656 EXPECT_TRUE(tester_context_.a_called_quit());
657}
658
James Robinson646469d2014-10-03 15:33:28 -0700659// Confirm that a service impl will be deleted if the app that connected to
660// it goes away.
661TEST_F(ApplicationManagerTest, BDeleted) {
662 AddLoaderForURL(GURL(kTestAURLString), std::string());
663 AddLoaderForURL(GURL(kTestBURLString), std::string());
664
665 TestAPtr a;
666 application_manager_->ConnectToService(GURL(kTestAURLString), &a);
667
668 a->CallB();
669 loop_.Run();
670
671 // Kills the a app.
672 application_manager_->SetLoaderForURL(scoped_ptr<ApplicationLoader>(),
673 GURL(kTestAURLString));
674 loop_.Run();
675
676 EXPECT_EQ(1, tester_context_.num_b_deletes());
677}
678
679// Confirm that the url of a service is correctly passed to another service that
680// it loads, and that it can be rejected.
681TEST_F(ApplicationManagerTest, ANoLoadB) {
682 // Any url can load a.
683 AddLoaderForURL(GURL(kTestAURLString), std::string());
684
685 // Only c can load b, so this will fail.
686 AddLoaderForURL(GURL(kTestBURLString), "test:TestC");
687
688 TestAPtr a;
689 application_manager_->ConnectToService(GURL(kTestAURLString), &a);
690 a->CallB();
691 loop_.Run();
692 EXPECT_EQ(0, tester_context_.num_b_calls());
693
694 EXPECT_FALSE(tester_context_.a_called_quit());
695 EXPECT_TRUE(tester_context_.tester_called_quit());
696}
697
698TEST_F(ApplicationManagerTest, NoServiceNoLoad) {
699 AddLoaderForURL(GURL(kTestAURLString), std::string());
700
701 // There is no TestC service implementation registered with
702 // ApplicationManager, so this cannot succeed (but also shouldn't crash).
703 TestCPtr c;
704 application_manager_->ConnectToService(GURL(kTestAURLString), &c);
Viet-Trung Luu01e64cf2015-07-08 09:55:53 -0700705 c.set_connection_error_handler(
706 []() { base::MessageLoop::current()->QuitWhenIdle(); });
James Robinson646469d2014-10-03 15:33:28 -0700707
708 loop_.Run();
709 EXPECT_TRUE(c.encountered_error());
710}
711
Aaron Boodmancd7b9112014-11-06 21:44:49 -0800712TEST_F(ApplicationManagerTest, MappedURLsShouldNotCauseDuplicateLoad) {
713 test_delegate_.AddMapping(GURL("foo:foo2"), GURL("foo:foo"));
714 // 1 because ApplicationManagerTest connects once at startup.
715 EXPECT_EQ(1, test_loader_->num_loads());
716
717 TestServicePtr test_service;
718 application_manager_->ConnectToService(GURL("foo:foo"), &test_service);
719 EXPECT_EQ(2, test_loader_->num_loads());
720
721 TestServicePtr test_service2;
722 application_manager_->ConnectToService(GURL("foo:foo2"), &test_service2);
723 EXPECT_EQ(2, test_loader_->num_loads());
724
725 TestServicePtr test_service3;
726 application_manager_->ConnectToService(GURL("bar:bar"), &test_service2);
727 EXPECT_EQ(3, test_loader_->num_loads());
728}
729
Benjamin Lerman75aef1d2015-01-21 12:04:39 +0100730TEST_F(ApplicationManagerTest, MappedURLsShouldWorkWithLoaders) {
731 TestApplicationLoader* custom_loader = new TestApplicationLoader;
732 TestContext context;
733 custom_loader->set_context(&context);
734 application_manager_->SetLoaderForURL(make_scoped_ptr(custom_loader),
735 GURL("mojo:foo"));
736 test_delegate_.AddMapping(GURL("mojo:foo2"), GURL("mojo:foo"));
737
738 TestServicePtr test_service;
739 application_manager_->ConnectToService(GURL("mojo:foo2"), &test_service);
740 EXPECT_EQ(1, custom_loader->num_loads());
741 custom_loader->set_context(nullptr);
742}
743
Benjamin Lermanc76642f2015-03-04 15:00:55 +0100744TEST_F(ApplicationManagerTest, TestQueryWithLoaders) {
745 TestApplicationLoader* url_loader = new TestApplicationLoader;
746 TestApplicationLoader* scheme_loader = new TestApplicationLoader;
747 application_manager_->SetLoaderForURL(
748 scoped_ptr<ApplicationLoader>(url_loader), GURL("test:test1"));
749 application_manager_->SetLoaderForScheme(
750 scoped_ptr<ApplicationLoader>(scheme_loader), "test");
751
752 // test::test1 should go to url_loader.
753 TestServicePtr test_service;
754 application_manager_->ConnectToService(GURL("test:test1?foo=bar"),
755 &test_service);
756 EXPECT_EQ(1, url_loader->num_loads());
757 EXPECT_EQ(0, scheme_loader->num_loads());
758
759 // test::test2 should go to scheme loader.
760 application_manager_->ConnectToService(GURL("test:test2?foo=bar"),
761 &test_service);
762 EXPECT_EQ(1, url_loader->num_loads());
763 EXPECT_EQ(1, scheme_loader->num_loads());
764}
765
Benjamin Lerman993869e2015-03-24 13:35:28 +0100766TEST_F(ApplicationManagerTest, TestEndApplicationClosure) {
767 ClosingApplicationLoader* loader = new ClosingApplicationLoader();
768 application_manager_->SetLoaderForScheme(
769 scoped_ptr<ApplicationLoader>(loader), "test");
770
771 bool called = false;
772 application_manager_->ConnectToApplication(
Viet-Trung Luud588c942016-05-09 16:49:45 -0700773 GURL("test:test"), GURL(), nullptr,
Benjamin Lerman993869e2015-03-24 13:35:28 +0100774 base::Bind(&QuitClosure, base::Unretained(&called)));
775 loop_.Run();
776 EXPECT_TRUE(called);
777}
778
Viet-Trung Luu36faa4d2015-03-04 18:08:18 -0800779} // namespace
780} // namespace shell