Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(103)

Unified Diff: mojo/shell/external_application_listener_unittest.cc

Issue 522443003: Accept inbound connections on unix domain socket (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@bug407782
Patch Set: Deleted extra curly brace, which was closing a namespace too early Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « mojo/shell/external_application_listener_posix.cc ('k') | mojo/shell/external_application_listener_win.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: mojo/shell/external_application_listener_unittest.cc
diff --git a/mojo/shell/external_application_listener_unittest.cc b/mojo/shell/external_application_listener_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..b7e2fa4cf9d176d477b3f34dab82be5ce2d2f5d8
--- /dev/null
+++ b/mojo/shell/external_application_listener_unittest.cc
@@ -0,0 +1,228 @@
+// Copyright 2014 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/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/threading/thread.h"
+#include "mojo/application_manager/application_manager.h"
+#include "mojo/common/common_type_converters.h"
+#include "mojo/public/interfaces/application/application.mojom.h"
+#include "mojo/public/interfaces/application/service_provider.mojom.h"
+#include "mojo/public/interfaces/application/shell.mojom.h"
+#include "mojo/shell/external_application_listener_posix.h"
+#include "mojo/shell/external_application_registrar.mojom.h"
+#include "mojo/shell/external_application_registrar_connection.h"
+#include "net/base/net_errors.h"
+#include "net/base/test_completion_callback.h"
+#include "net/socket/unix_domain_client_socket_posix.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace mojo {
+namespace shell {
+
+class ExternalApplicationListenerTest : public testing::Test {
+ public:
+ ExternalApplicationListenerTest() : io_thread_("io thread") {}
+ virtual ~ExternalApplicationListenerTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ base::Thread::Options options;
+ options.message_loop_type = base::MessageLoop::TYPE_IO;
+ io_thread_.StartWithOptions(options);
+
+ listener_.reset(new ExternalApplicationListenerPosix(
+ loop_.task_runner(), io_thread_.task_runner()));
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+ socket_path_ = temp_dir_.path().Append(FILE_PATH_LITERAL("socket"));
+ }
+
+ protected:
+ base::MessageLoop loop_;
+ base::RunLoop run_loop_;
+ base::Thread io_thread_;
+
+ base::ScopedTempDir temp_dir_;
+ ApplicationManager application_manager_;
+ base::FilePath socket_path_;
+ scoped_ptr<ExternalApplicationListener> listener_;
+};
+
+namespace {
+class StubShellImpl : public InterfaceImpl<Shell> {
+ private:
+ virtual void ConnectToApplication(
+ const String& requestor_url,
+ InterfaceRequest<ServiceProvider> in_service_provider) MOJO_OVERRIDE {
+ ServiceProviderPtr out_service_provider;
+ out_service_provider.Bind(in_service_provider.PassMessagePipe());
+ client()->AcceptConnection(requestor_url, out_service_provider.Pass());
+ }
+};
+
+void DoLocalRegister(const GURL& app_url, ScopedMessagePipeHandle shell) {
+ BindToPipe(new StubShellImpl, shell.Pass());
+}
+
+void QuitLoopOnConnect(scoped_refptr<base::TaskRunner> loop,
+ base::Closure quit_callback,
+ int rv) {
+ EXPECT_EQ(net::OK, rv);
+ loop->PostTask(FROM_HERE, quit_callback);
+}
+
+void ConnectOnIOThread(const base::FilePath& socket_path,
+ scoped_refptr<base::TaskRunner> to_quit,
+ base::Closure quit_callback) {
+ ExternalApplicationRegistrarConnection connection(socket_path);
+ connection.Connect(base::Bind(&QuitLoopOnConnect, to_quit, quit_callback));
+}
+} // namespace
+
+TEST_F(ExternalApplicationListenerTest, ConnectConnection) {
+ listener_->ListenInBackground(socket_path_, base::Bind(&DoLocalRegister));
+ listener_->WaitForListening();
+ io_thread_.task_runner()->PostTask(FROM_HERE,
+ base::Bind(&ConnectOnIOThread,
+ socket_path_,
+ loop_.task_runner(),
+ run_loop_.QuitClosure()));
+ run_loop_.Run();
+}
+
+namespace {
+class QuitLoopOnConnectApplicationImpl : public InterfaceImpl<Application> {
+ public:
+ QuitLoopOnConnectApplicationImpl(const std::string& url,
+ scoped_refptr<base::TaskRunner> loop,
+ base::Closure quit_callback)
+ : url_(url), to_quit_(loop), quit_callback_(quit_callback) {}
+
+ private:
+ virtual void Initialize(Array<String> args) MOJO_OVERRIDE {}
+
+ virtual void AcceptConnection(const String& requestor_url,
+ ServiceProviderPtr p) MOJO_OVERRIDE {
+ DVLOG(1) << url_ << " accepting connection from " << requestor_url;
+ to_quit_->PostTask(FROM_HERE, quit_callback_);
+ }
+
+ const std::string url_;
+ scoped_refptr<base::TaskRunner> to_quit_;
+ base::Closure quit_callback_;
+};
+
+class FakeExternalApplication {
+ public:
+ FakeExternalApplication(const std::string& url) : url_(url) {}
+
+ void ConnectSynchronously(const base::FilePath& socket_path) {
+ connection_.reset(new ExternalApplicationRegistrarConnection(socket_path));
+ net::TestCompletionCallback connect_callback;
+ connection_->Connect(connect_callback.callback());
+ connect_callback.WaitForResult();
+ }
+
+ // application_impl is the the actual implementation to be registered.
+ void Register(scoped_ptr<InterfaceImpl<Application>> application_impl,
+ base::Closure register_complete_callback) {
+ connection_->Register(GURL(url_), &ptr_, register_complete_callback);
+ application_impl_ = application_impl.Pass();
+ ptr_.set_client(application_impl_.get());
+ }
+
+ void ConnectToAppByUrl(std::string app_url) {
+ ServiceProviderPtr sp;
+ ptr_->ConnectToApplication(app_url, Get(&sp));
+ }
+
+ const std::string& url() { return url_; }
+
+ private:
+ const std::string url_;
+ scoped_ptr<InterfaceImpl<Application>> application_impl_;
+ ShellPtr ptr_;
+
+ scoped_ptr<ExternalApplicationRegistrarConnection> connection_;
+};
+
+void ConnectToApp(FakeExternalApplication* connector,
+ FakeExternalApplication* connectee) {
+ connector->ConnectToAppByUrl(connectee->url());
+}
+
+void NoOp() {
+}
+
+void ConnectAndRegisterOnIOThread(const base::FilePath& socket_path,
+ scoped_refptr<base::TaskRunner> loop,
+ base::Closure quit_callback,
+ FakeExternalApplication* connector,
+ FakeExternalApplication* connectee) {
+ // Connect the first app to the registrar.
+ connector->ConnectSynchronously(socket_path);
+ // connector will use this implementation of the Mojo Application interface
+ // once registration complete.
+ scoped_ptr<QuitLoopOnConnectApplicationImpl> connector_app_impl(
+ new QuitLoopOnConnectApplicationImpl(
+ connector->url(), loop, quit_callback));
+ // Since connectee won't be ready when connector is done registering, pass
+ // in a do-nothing callback.
+ connector->Register(connector_app_impl.PassAs<InterfaceImpl<Application>>(),
+ base::Bind(&NoOp));
+
+ // Connect the second app to the registrar.
+ connectee->ConnectSynchronously(socket_path);
+ scoped_ptr<QuitLoopOnConnectApplicationImpl> connectee_app_impl(
+ new QuitLoopOnConnectApplicationImpl(
+ connectee->url(), loop, quit_callback));
+ // After connectee is successfully registered, connector should be
+ // able to connect to is by URL. Pass in a callback to attempt the
+ // app -> app connection.
+ connectee->Register(connectee_app_impl.PassAs<InterfaceImpl<Application>>(),
+ base::Bind(&ConnectToApp, connector, connectee));
+}
+
+void DestroyOnIOThread(scoped_ptr<FakeExternalApplication> doomed1,
+ scoped_ptr<FakeExternalApplication> doomed2) {
+}
+} // namespace
+
+// Create two external applications, have them discover and connect to
+// the registrar, and then have one app connect to the other by URL.
+TEST_F(ExternalApplicationListenerTest, ConnectTwoExternalApplications) {
+ listener_->ListenInBackground(
+ socket_path_,
+ base::Bind(&ApplicationManager::RegisterExternalApplication,
+ base::Unretained(&application_manager_)));
+ listener_->WaitForListening();
+
+ // Create two external apps.
+ scoped_ptr<FakeExternalApplication> supersweet_app(
+ new FakeExternalApplication("http://my.supersweet.app"));
+ scoped_ptr<FakeExternalApplication> awesome_app(
+ new FakeExternalApplication("http://my.awesome.app"));
+
+ // Connecting and talking to the registrar has to happen on the IO thread.
+ io_thread_.task_runner()->PostTask(FROM_HERE,
+ base::Bind(&ConnectAndRegisterOnIOThread,
+ socket_path_,
+ loop_.task_runner(),
+ run_loop_.QuitClosure(),
+ supersweet_app.get(),
+ awesome_app.get()));
+ run_loop_.Run();
+
+ // The apps need to be destroyed on the thread where they did socket stuff.
+ io_thread_.task_runner()->PostTask(FROM_HERE,
+ base::Bind(&DestroyOnIOThread,
+ base::Passed(&supersweet_app),
+ base::Passed(&awesome_app)));
+}
+
+} // namespace shell
+} // namespace mojo
« no previous file with comments | « mojo/shell/external_application_listener_posix.cc ('k') | mojo/shell/external_application_listener_win.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698