blob: 0b1dca2ae32bc4a29209d96bbda2d319fa9e1307 [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/at_exit.h"
#include "base/bind.h"
#include "base/macros.h"
#include "base/memory/scoped_vector.h"
#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "mojo/application/public/cpp/application_connection.h"
#include "mojo/application/public/cpp/application_delegate.h"
#include "mojo/application/public/cpp/application_impl.h"
#include "mojo/application/public/cpp/interface_factory.h"
#include "mojo/application/public/interfaces/content_handler.mojom.h"
#include "mojo/application/public/interfaces/service_provider.mojom.h"
#include "mojo/package_manager/package_manager_impl.h"
#include "mojo/shell/application_loader.h"
#include "mojo/shell/application_manager.h"
#include "mojo/shell/connect_util.h"
#include "mojo/shell/fetcher.h"
#include "mojo/shell/test_package_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/mojo/src/mojo/public/cpp/bindings/strong_binding.h"
namespace mojo {
namespace package_manager {
namespace test {
namespace {
const char kTestMimeType[] = "test/mime-type";
class TestFetcher : public shell::Fetcher {
public:
TestFetcher(const FetchCallback& fetch_callback,
const GURL& url,
const std::string& mime_type)
: Fetcher(fetch_callback), url_(url), mime_type_(mime_type) {
loader_callback_.Run(make_scoped_ptr(this));
}
~TestFetcher() override {}
// Fetcher:
const GURL& GetURL() const override { return url_; }
GURL GetRedirectURL() const override { return GURL("yyy"); }
GURL GetRedirectReferer() const override { return GURL(); }
URLResponsePtr AsURLResponse(base::TaskRunner* task_runner,
uint32_t skip) override {
return URLResponse::New().Pass();
}
void AsPath(
base::TaskRunner* task_runner,
base::Callback<void(const base::FilePath&, bool)> callback) override {}
std::string MimeType() override { return mime_type_; }
bool HasMojoMagic() override { return false; }
bool PeekFirstLine(std::string* line) override { return false; }
private:
const GURL url_;
const std::string mime_type_;
DISALLOW_COPY_AND_ASSIGN(TestFetcher);
};
void QuitClosure(bool* value) {
*value = true;
base::MessageLoop::current()->QuitWhenIdle();
}
class TestContentHandler : public ContentHandler, public ApplicationDelegate {
public:
TestContentHandler(ApplicationConnection* connection,
InterfaceRequest<ContentHandler> request)
: binding_(this, request.Pass()) {}
// ContentHandler:
void StartApplication(
InterfaceRequest<Application> application_request,
URLResponsePtr response,
const Callback<void()>& destruct_callback) override {
apps_.push_back(new ApplicationImpl(this, application_request.Pass()));
destruct_callback.Run();
}
private:
StrongBinding<ContentHandler> binding_;
ScopedVector<ApplicationImpl> apps_;
DISALLOW_COPY_AND_ASSIGN(TestContentHandler);
};
class TestApplicationLoader : public shell::ApplicationLoader,
public ApplicationDelegate,
public InterfaceFactory<ContentHandler> {
public:
TestApplicationLoader() : num_loads_(0) {}
~TestApplicationLoader() override {}
int num_loads() const { return num_loads_; }
const GURL& last_requestor_url() const { return last_requestor_url_; }
private:
// ApplicationLoader implementation.
void Load(const GURL& url,
InterfaceRequest<Application> application_request) override {
++num_loads_;
test_app_.reset(new ApplicationImpl(this, application_request.Pass()));
}
// ApplicationDelegate implementation.
bool ConfigureIncomingConnection(ApplicationConnection* connection) override {
connection->AddService<ContentHandler>(this);
last_requestor_url_ = GURL(connection->GetRemoteApplicationURL());
return true;
}
// InterfaceFactory<ContentHandler> implementation.
void Create(ApplicationConnection* connection,
InterfaceRequest<ContentHandler> request) override {
new TestContentHandler(connection, request.Pass());
}
scoped_ptr<ApplicationImpl> test_app_;
int num_loads_;
GURL last_requestor_url_;
DISALLOW_COPY_AND_ASSIGN(TestApplicationLoader);
};
class TestPackageManager : public PackageManagerImpl {
public:
explicit TestPackageManager(const base::FilePath& package_path)
: PackageManagerImpl(package_path, nullptr),
mime_type_(kTestMimeType) {}
~TestPackageManager() override {}
void set_mime_type(const std::string& mime_type) {
mime_type_ = mime_type;
}
// PackageManagerImpl:
void FetchRequest(
URLRequestPtr request,
const shell::Fetcher::FetchCallback& loader_callback) override {
new TestFetcher(loader_callback, GURL(request->url), mime_type_);
}
private:
std::string mime_type_;
DISALLOW_COPY_AND_ASSIGN(TestPackageManager);
};
} // namespace
class ContentHandlerTest : public testing::Test {
public:
ContentHandlerTest()
: content_handler_url_("http://test.content.handler"),
requestor_url_("http://requestor.url") {}
~ContentHandlerTest() override {}
void SetUp() override {
base::FilePath shell_dir;
PathService::Get(base::DIR_MODULE, &shell_dir);
test_package_manager_ = new TestPackageManager(shell_dir);
test_package_manager_->RegisterContentHandler(kTestMimeType,
content_handler_url_);
application_manager_.reset(new shell::ApplicationManager(
make_scoped_ptr(test_package_manager_)));
}
void TearDown() override {
test_package_manager_ = nullptr;
application_manager_.reset();
}
protected:
const GURL content_handler_url_;
const GURL requestor_url_;
base::MessageLoop loop_;
scoped_ptr<shell::ApplicationManager> application_manager_;
// Owned by ApplicationManager.
TestPackageManager* test_package_manager_;
DISALLOW_COPY_AND_ASSIGN(ContentHandlerTest);
};
TEST_F(ContentHandlerTest, ContentHandlerConnectionGetsRequestorURL) {
TestApplicationLoader* loader = new TestApplicationLoader;
application_manager_->SetLoaderForURL(
scoped_ptr<shell::ApplicationLoader>(loader),
content_handler_url_);
bool called = false;
scoped_ptr<shell::ConnectToApplicationParams> params(
new shell::ConnectToApplicationParams);
params->set_source(shell::Identity(requestor_url_));
params->SetTargetURL(GURL("test:test"));
params->set_on_application_end(
base::Bind(&QuitClosure, base::Unretained(&called)));
application_manager_->ConnectToApplication(params.Pass());
loop_.Run();
EXPECT_TRUE(called);
ASSERT_EQ(1, loader->num_loads());
EXPECT_EQ(requestor_url_, loader->last_requestor_url());
}
TEST_F(ContentHandlerTest,
MultipleConnectionsToContentHandlerGetSameContentHandlerId) {
TestApplicationLoader* content_handler_loader = new TestApplicationLoader;
application_manager_->SetLoaderForURL(
scoped_ptr<shell::ApplicationLoader>(content_handler_loader),
content_handler_url_);
uint32_t content_handler_id;
{
base::RunLoop run_loop;
scoped_ptr<shell::ConnectToApplicationParams> params(
new shell::ConnectToApplicationParams);
params->set_source(shell::Identity(requestor_url_));
params->SetTargetURL(GURL("test:test"));
params->set_connect_callback([&content_handler_id, &run_loop](uint32_t t) {
content_handler_id = t;
run_loop.Quit();
});
application_manager_->ConnectToApplication(params.Pass());
run_loop.Run();
EXPECT_NE(Shell::kInvalidContentHandlerID, content_handler_id);
}
uint32_t content_handler_id2;
{
base::RunLoop run_loop;
scoped_ptr<shell::ConnectToApplicationParams> params(
new shell::ConnectToApplicationParams);
params->set_source(shell::Identity(requestor_url_));
params->SetTargetURL(GURL("test:test"));
params->set_connect_callback([&content_handler_id2, &run_loop](uint32_t t) {
content_handler_id2 = t;
run_loop.Quit();
});
application_manager_->ConnectToApplication(params.Pass());
run_loop.Run();
EXPECT_NE(Shell::kInvalidContentHandlerID, content_handler_id2);
}
EXPECT_EQ(content_handler_id, content_handler_id2);
}
TEST_F(ContentHandlerTest, DifferedContentHandlersGetDifferentIDs) {
TestApplicationLoader* content_handler_loader = new TestApplicationLoader;
application_manager_->SetLoaderForURL(
scoped_ptr<shell::ApplicationLoader>(content_handler_loader),
content_handler_url_);
uint32_t content_handler_id;
{
base::RunLoop run_loop;
scoped_ptr<shell::ConnectToApplicationParams> params(
new shell::ConnectToApplicationParams);
params->set_source(shell::Identity(requestor_url_));
params->SetTargetURL(GURL("test:test"));
params->set_connect_callback([&content_handler_id, &run_loop](uint32_t t) {
content_handler_id = t;
run_loop.Quit();
});
application_manager_->ConnectToApplication(params.Pass());
run_loop.Run();
EXPECT_NE(Shell::kInvalidContentHandlerID, content_handler_id);
}
const std::string mime_type2 = "test/mime-type2";
const GURL content_handler_url2("http://test.content.handler2");
test_package_manager_->set_mime_type(mime_type2);
test_package_manager_->RegisterContentHandler(mime_type2,
content_handler_url2);
TestApplicationLoader* content_handler_loader2 = new TestApplicationLoader;
application_manager_->SetLoaderForURL(
scoped_ptr<shell::ApplicationLoader>(content_handler_loader2),
content_handler_url2);
uint32_t content_handler_id2;
{
base::RunLoop run_loop;
scoped_ptr<shell::ConnectToApplicationParams> params(
new shell::ConnectToApplicationParams);
params->set_source(shell::Identity(requestor_url_));
params->SetTargetURL(GURL("test2:test2"));
params->set_connect_callback([&content_handler_id2, &run_loop](uint32_t t) {
content_handler_id2 = t;
run_loop.Quit();
});
application_manager_->ConnectToApplication(params.Pass());
run_loop.Run();
EXPECT_NE(Shell::kInvalidContentHandlerID, content_handler_id2);
}
EXPECT_NE(content_handler_id, content_handler_id2);
}
TEST_F(ContentHandlerTest,
ConnectWithNoContentHandlerGetsInvalidContentHandlerId) {
application_manager_->SetLoaderForURL(
scoped_ptr<shell::ApplicationLoader>(new TestApplicationLoader),
GURL("test:test"));
uint32_t content_handler_id = 1u;
scoped_ptr<shell::ConnectToApplicationParams> params(
new shell::ConnectToApplicationParams);
params->SetTargetURL(GURL("test:test"));
params->set_connect_callback(
[&content_handler_id](uint32_t t) { content_handler_id = t; });
application_manager_->ConnectToApplication(params.Pass());
EXPECT_EQ(0u, content_handler_id);
}
} // namespace test
} // namespace package_manager
} // namespace mojo