| // 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 |