blob: 3a4ad0367f190caee9ab30a94cd4b07a9e09ce1e [file] [log] [blame]
Viet-Trung Luu70d849d2015-05-11 16:57:08 -07001// Copyright 2015 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
5// This is a simple example application (with an embeddable view), which embeds
6// the Moterm view, uses it to prompt the user, etc.
7
8#include <string.h>
9
10#include <algorithm>
Vardhan Mudunuruc3575c42016-02-11 15:08:21 -080011#include <utility>
Viet-Trung Luu70d849d2015-05-11 16:57:08 -070012
13#include "base/bind.h"
14#include "base/macros.h"
15#include "base/memory/weak_ptr.h"
Viet-Trung Luu70d849d2015-05-11 16:57:08 -070016#include "base/strings/string_util.h"
17#include "base/strings/stringprintf.h"
Jeff Brown5a846ea2016-01-26 15:53:07 -080018#include "mojo/common/binding_set.h"
Viet-Trung Luu8f8c2152016-05-31 13:11:00 -070019#include "mojo/environment/scoped_chromium_init.h"
Viet-Trung Luu70d849d2015-05-11 16:57:08 -070020#include "mojo/public/c/system/main.h"
Viet-Trung Luu70d849d2015-05-11 16:57:08 -070021#include "mojo/public/cpp/application/connect.h"
Viet-Trung Luu8f8c2152016-05-31 13:11:00 -070022#include "mojo/public/cpp/application/run_application.h"
Viet-Trung Luu70d849d2015-05-11 16:57:08 -070023#include "mojo/public/cpp/bindings/array.h"
Jeff Brown5a846ea2016-01-26 15:53:07 -080024#include "mojo/public/cpp/bindings/strong_binding.h"
Viet-Trung Luu70d849d2015-05-11 16:57:08 -070025#include "mojo/public/interfaces/application/service_provider.mojom.h"
26#include "mojo/public/interfaces/application/shell.mojom.h"
Viet-Trung Luu08e339a2015-10-10 01:03:09 -070027#include "mojo/services/files/interfaces/file.mojom.h"
28#include "mojo/services/files/interfaces/types.mojom.h"
Viet-Trung Luu0f4f3ba2015-10-10 01:08:40 -070029#include "mojo/services/terminal/interfaces/terminal.mojom.h"
30#include "mojo/services/terminal/interfaces/terminal_client.mojom.h"
Jeff Brown5a846ea2016-01-26 15:53:07 -080031#include "mojo/services/ui/views/interfaces/view_manager.mojom.h"
32#include "mojo/services/ui/views/interfaces/view_provider.mojom.h"
33#include "mojo/services/ui/views/interfaces/views.mojom.h"
Jeff Brown83365b12016-02-10 11:08:14 -080034#include "mojo/ui/view_provider_app.h"
Viet-Trung Luu70d849d2015-05-11 16:57:08 -070035
36// Kind of like |fputs()| (doesn't wait for result).
37void Fputs(mojo::files::File* file, const char* s) {
38 size_t length = strlen(s);
James Robinsondc335c02015-10-09 17:23:30 -070039 auto a = mojo::Array<uint8_t>::New(length);
Viet-Trung Luu70d849d2015-05-11 16:57:08 -070040 memcpy(&a[0], s, length);
41
John Grossman87fe5142015-10-02 10:11:43 -070042 file->Write(a.Pass(), 0, mojo::files::Whence::FROM_CURRENT,
Viet-Trung Luu70d849d2015-05-11 16:57:08 -070043 mojo::files::File::WriteCallback());
44}
45
Jeff Brown5a846ea2016-01-26 15:53:07 -080046class MotermExampleAppView {
Viet-Trung Luu70d849d2015-05-11 16:57:08 -070047 public:
Jeff Brown5a846ea2016-01-26 15:53:07 -080048 MotermExampleAppView(
49 mojo::Shell* shell,
Jeff Brown83365b12016-02-10 11:08:14 -080050 mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request)
Jeff Brown5a846ea2016-01-26 15:53:07 -080051 : shell_(shell), weak_factory_(this) {
52 // Connect to the moterm app.
53 LOG(INFO) << "Connecting to moterm";
54 mojo::ServiceProviderPtr moterm_app;
55 shell->ConnectToApplication("mojo:moterm", GetProxy(&moterm_app), nullptr);
Viet-Trung Luu70d849d2015-05-11 16:57:08 -070056
Jeff Brown5a846ea2016-01-26 15:53:07 -080057 // Create the moterm view and pass it back to the client directly.
Viet-Trung Luuc5cfd312016-04-25 16:57:51 -070058 mojo::ConnectToService(moterm_app.get(), GetProxy(&moterm_view_provider_));
Jeff Brown5a846ea2016-01-26 15:53:07 -080059 mojo::ServiceProviderPtr moterm_service_provider;
Viet-Trung Luudb068982016-05-24 13:15:55 -070060 moterm_view_provider_->CreateView(view_owner_request.Pass(),
61 GetProxy(&moterm_service_provider));
Jeff Brown5a846ea2016-01-26 15:53:07 -080062
63 // Connect to the moterm terminal service associated with the view
64 // we just created.
Viet-Trung Luuc5cfd312016-04-25 16:57:51 -070065 mojo::ConnectToService(moterm_service_provider.get(),
66 GetProxy(&moterm_terminal_));
Jeff Brown5a846ea2016-01-26 15:53:07 -080067
68 // Start running.
Viet-Trung Luu70d849d2015-05-11 16:57:08 -070069 StartPrompt(true);
70 }
71
Jeff Brown5a846ea2016-01-26 15:53:07 -080072 ~MotermExampleAppView() {}
Viet-Trung Luu70d849d2015-05-11 16:57:08 -070073
74 private:
75 void Resize() {
76 moterm_terminal_->SetSize(0, 0, false, [](mojo::files::Error error,
77 uint32_t rows, uint32_t columns) {
John Grossman87fe5142015-10-02 10:11:43 -070078 DCHECK_EQ(error, mojo::files::Error::OK);
Viet-Trung Luu70d849d2015-05-11 16:57:08 -070079 DVLOG(1) << "New size: " << rows << "x" << columns;
80 });
81 }
82
83 void StartPrompt(bool first_time) {
84 if (!moterm_file_) {
85 moterm_terminal_->Connect(GetProxy(&moterm_file_), false,
86 [](mojo::files::Error error) {
John Grossman87fe5142015-10-02 10:11:43 -070087 DCHECK_EQ(error, mojo::files::Error::OK);
Viet-Trung Luu70d849d2015-05-11 16:57:08 -070088 });
89 }
90
91 if (first_time) {
92 // Display some welcome text.
93 Fputs(moterm_file_.get(),
94 "Welcome to "
95 "\x1b[1m\x1b[34mM\x1b[31mo\x1b[33mt\x1b[34me\x1b[32mr\x1b[31mm\n"
96 "\n");
97 }
98
99 Fputs(moterm_file_.get(), "\x1b[0m\nWhere do you want to go today?\n:) ");
John Grossman87fe5142015-10-02 10:11:43 -0700100 moterm_file_->Read(1000, 0, mojo::files::Whence::FROM_CURRENT,
Viet-Trung Luu70d849d2015-05-11 16:57:08 -0700101 base::Bind(&MotermExampleAppView::OnInputFromPrompt,
102 weak_factory_.GetWeakPtr()));
103 }
104 void OnInputFromPrompt(mojo::files::Error error,
105 mojo::Array<uint8_t> bytes_read) {
John Grossman87fe5142015-10-02 10:11:43 -0700106 if (error != mojo::files::Error::OK || !bytes_read) {
Viet-Trung Luu70d849d2015-05-11 16:57:08 -0700107 // TODO(vtl): Handle errors?
108 NOTIMPLEMENTED();
109 return;
110 }
111
112 std::string dest_url;
113 if (bytes_read.size() >= 1) {
114 base::TrimWhitespaceASCII(
115 std::string(reinterpret_cast<const char*>(&bytes_read[0]),
116 bytes_read.size()),
117 base::TRIM_ALL, &dest_url);
118 }
119
120 if (dest_url.empty()) {
121 Fputs(moterm_file_.get(), "\nError: no destination URL given\n");
122 StartPrompt(false);
123 return;
124 }
125
126 Fputs(moterm_file_.get(),
127 base::StringPrintf("\nGoing to %s ...\n", dest_url.c_str()).c_str());
128 moterm_file_.reset();
129
130 mojo::ServiceProviderPtr dest_sp;
131 shell_->ConnectToApplication(dest_url, GetProxy(&dest_sp), nullptr);
132 mojo::terminal::TerminalClientPtr dest_terminal_client;
Viet-Trung Luuc5cfd312016-04-25 16:57:51 -0700133 mojo::ConnectToService(dest_sp.get(), GetProxy(&dest_terminal_client));
Viet-Trung Luu70d849d2015-05-11 16:57:08 -0700134 moterm_terminal_->ConnectToClient(
Vardhan Mudunuruc3575c42016-02-11 15:08:21 -0800135 std::move(dest_terminal_client), true,
Viet-Trung Luu70d849d2015-05-11 16:57:08 -0700136 base::Bind(&MotermExampleAppView::OnDestinationDone,
137 weak_factory_.GetWeakPtr()));
138 }
139 void OnDestinationDone(mojo::files::Error error) {
140 // We should always succeed. (It'll only fail on synchronous failures, which
141 // only occur when it's busy.)
John Grossman87fe5142015-10-02 10:11:43 -0700142 DCHECK_EQ(error, mojo::files::Error::OK);
Viet-Trung Luu70d849d2015-05-11 16:57:08 -0700143 StartPrompt(false);
144 }
145
Viet-Trung Luu70d849d2015-05-11 16:57:08 -0700146 mojo::Shell* const shell_;
Jeff Brown5a846ea2016-01-26 15:53:07 -0800147 mojo::ui::ViewProviderPtr moterm_view_provider_;
Viet-Trung Luu70d849d2015-05-11 16:57:08 -0700148
Viet-Trung Luu70d849d2015-05-11 16:57:08 -0700149 mojo::terminal::TerminalPtr moterm_terminal_;
150 // Valid while prompting.
151 mojo::files::FilePtr moterm_file_;
152
153 base::WeakPtrFactory<MotermExampleAppView> weak_factory_;
154
155 DISALLOW_COPY_AND_ASSIGN(MotermExampleAppView);
156};
157
Jeff Brown83365b12016-02-10 11:08:14 -0800158class MotermExampleApp : public mojo::ui::ViewProviderApp {
Viet-Trung Luu70d849d2015-05-11 16:57:08 -0700159 public:
Jeff Brown83365b12016-02-10 11:08:14 -0800160 MotermExampleApp() {}
Viet-Trung Luu70d849d2015-05-11 16:57:08 -0700161 ~MotermExampleApp() override {}
162
Jeff Brown83365b12016-02-10 11:08:14 -0800163 // |ViewProviderApp|:
164 void CreateView(
165 const std::string& connection_url,
166 mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request,
Viet-Trung Luudb068982016-05-24 13:15:55 -0700167 mojo::InterfaceRequest<mojo::ServiceProvider> services) override {
Viet-Trung Luu8f8c2152016-05-31 13:11:00 -0700168 new MotermExampleAppView(shell(), view_owner_request.Pass());
Jeff Brown83365b12016-02-10 11:08:14 -0800169 }
170
Viet-Trung Luu70d849d2015-05-11 16:57:08 -0700171 private:
Viet-Trung Luu70d849d2015-05-11 16:57:08 -0700172 DISALLOW_COPY_AND_ASSIGN(MotermExampleApp);
173};
174
175MojoResult MojoMain(MojoHandle application_request) {
Viet-Trung Luu8f8c2152016-05-31 13:11:00 -0700176 mojo::ScopedChromiumInit init;
177 MotermExampleApp moterm_example_app;
178 return mojo::RunApplication(application_request, &moterm_example_app);
Viet-Trung Luu70d849d2015-05-11 16:57:08 -0700179}