Viet-Trung Luu | 70d849d | 2015-05-11 16:57:08 -0700 | [diff] [blame] | 1 | // 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 Mudunuru | c3575c4 | 2016-02-11 15:08:21 -0800 | [diff] [blame] | 11 | #include <utility> |
Viet-Trung Luu | 70d849d | 2015-05-11 16:57:08 -0700 | [diff] [blame] | 12 | |
| 13 | #include "base/bind.h" |
| 14 | #include "base/macros.h" |
| 15 | #include "base/memory/weak_ptr.h" |
Viet-Trung Luu | 70d849d | 2015-05-11 16:57:08 -0700 | [diff] [blame] | 16 | #include "base/strings/string_util.h" |
| 17 | #include "base/strings/stringprintf.h" |
Jeff Brown | 5a846ea | 2016-01-26 15:53:07 -0800 | [diff] [blame] | 18 | #include "mojo/common/binding_set.h" |
Viet-Trung Luu | 8f8c215 | 2016-05-31 13:11:00 -0700 | [diff] [blame] | 19 | #include "mojo/environment/scoped_chromium_init.h" |
Viet-Trung Luu | 70d849d | 2015-05-11 16:57:08 -0700 | [diff] [blame] | 20 | #include "mojo/public/c/system/main.h" |
Viet-Trung Luu | 70d849d | 2015-05-11 16:57:08 -0700 | [diff] [blame] | 21 | #include "mojo/public/cpp/application/connect.h" |
Viet-Trung Luu | 8f8c215 | 2016-05-31 13:11:00 -0700 | [diff] [blame] | 22 | #include "mojo/public/cpp/application/run_application.h" |
Viet-Trung Luu | 70d849d | 2015-05-11 16:57:08 -0700 | [diff] [blame] | 23 | #include "mojo/public/cpp/bindings/array.h" |
Jeff Brown | 5a846ea | 2016-01-26 15:53:07 -0800 | [diff] [blame] | 24 | #include "mojo/public/cpp/bindings/strong_binding.h" |
Viet-Trung Luu | 70d849d | 2015-05-11 16:57:08 -0700 | [diff] [blame] | 25 | #include "mojo/public/interfaces/application/service_provider.mojom.h" |
| 26 | #include "mojo/public/interfaces/application/shell.mojom.h" |
Viet-Trung Luu | 08e339a | 2015-10-10 01:03:09 -0700 | [diff] [blame] | 27 | #include "mojo/services/files/interfaces/file.mojom.h" |
| 28 | #include "mojo/services/files/interfaces/types.mojom.h" |
Viet-Trung Luu | 0f4f3ba | 2015-10-10 01:08:40 -0700 | [diff] [blame] | 29 | #include "mojo/services/terminal/interfaces/terminal.mojom.h" |
| 30 | #include "mojo/services/terminal/interfaces/terminal_client.mojom.h" |
Jeff Brown | 5a846ea | 2016-01-26 15:53:07 -0800 | [diff] [blame] | 31 | #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 Brown | 83365b1 | 2016-02-10 11:08:14 -0800 | [diff] [blame] | 34 | #include "mojo/ui/view_provider_app.h" |
Viet-Trung Luu | 70d849d | 2015-05-11 16:57:08 -0700 | [diff] [blame] | 35 | |
| 36 | // Kind of like |fputs()| (doesn't wait for result). |
| 37 | void Fputs(mojo::files::File* file, const char* s) { |
| 38 | size_t length = strlen(s); |
James Robinson | dc335c0 | 2015-10-09 17:23:30 -0700 | [diff] [blame] | 39 | auto a = mojo::Array<uint8_t>::New(length); |
Viet-Trung Luu | 70d849d | 2015-05-11 16:57:08 -0700 | [diff] [blame] | 40 | memcpy(&a[0], s, length); |
| 41 | |
John Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 42 | file->Write(a.Pass(), 0, mojo::files::Whence::FROM_CURRENT, |
Viet-Trung Luu | 70d849d | 2015-05-11 16:57:08 -0700 | [diff] [blame] | 43 | mojo::files::File::WriteCallback()); |
| 44 | } |
| 45 | |
Jeff Brown | 5a846ea | 2016-01-26 15:53:07 -0800 | [diff] [blame] | 46 | class MotermExampleAppView { |
Viet-Trung Luu | 70d849d | 2015-05-11 16:57:08 -0700 | [diff] [blame] | 47 | public: |
Jeff Brown | 5a846ea | 2016-01-26 15:53:07 -0800 | [diff] [blame] | 48 | MotermExampleAppView( |
| 49 | mojo::Shell* shell, |
Jeff Brown | 83365b1 | 2016-02-10 11:08:14 -0800 | [diff] [blame] | 50 | mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request) |
Jeff Brown | 5a846ea | 2016-01-26 15:53:07 -0800 | [diff] [blame] | 51 | : 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 Luu | 70d849d | 2015-05-11 16:57:08 -0700 | [diff] [blame] | 56 | |
Jeff Brown | 5a846ea | 2016-01-26 15:53:07 -0800 | [diff] [blame] | 57 | // Create the moterm view and pass it back to the client directly. |
Viet-Trung Luu | c5cfd31 | 2016-04-25 16:57:51 -0700 | [diff] [blame] | 58 | mojo::ConnectToService(moterm_app.get(), GetProxy(&moterm_view_provider_)); |
Jeff Brown | 5a846ea | 2016-01-26 15:53:07 -0800 | [diff] [blame] | 59 | mojo::ServiceProviderPtr moterm_service_provider; |
Viet-Trung Luu | db06898 | 2016-05-24 13:15:55 -0700 | [diff] [blame] | 60 | moterm_view_provider_->CreateView(view_owner_request.Pass(), |
| 61 | GetProxy(&moterm_service_provider)); |
Jeff Brown | 5a846ea | 2016-01-26 15:53:07 -0800 | [diff] [blame] | 62 | |
| 63 | // Connect to the moterm terminal service associated with the view |
| 64 | // we just created. |
Viet-Trung Luu | c5cfd31 | 2016-04-25 16:57:51 -0700 | [diff] [blame] | 65 | mojo::ConnectToService(moterm_service_provider.get(), |
| 66 | GetProxy(&moterm_terminal_)); |
Jeff Brown | 5a846ea | 2016-01-26 15:53:07 -0800 | [diff] [blame] | 67 | |
| 68 | // Start running. |
Viet-Trung Luu | 70d849d | 2015-05-11 16:57:08 -0700 | [diff] [blame] | 69 | StartPrompt(true); |
| 70 | } |
| 71 | |
Jeff Brown | 5a846ea | 2016-01-26 15:53:07 -0800 | [diff] [blame] | 72 | ~MotermExampleAppView() {} |
Viet-Trung Luu | 70d849d | 2015-05-11 16:57:08 -0700 | [diff] [blame] | 73 | |
| 74 | private: |
| 75 | void Resize() { |
| 76 | moterm_terminal_->SetSize(0, 0, false, [](mojo::files::Error error, |
| 77 | uint32_t rows, uint32_t columns) { |
John Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 78 | DCHECK_EQ(error, mojo::files::Error::OK); |
Viet-Trung Luu | 70d849d | 2015-05-11 16:57:08 -0700 | [diff] [blame] | 79 | 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 Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 87 | DCHECK_EQ(error, mojo::files::Error::OK); |
Viet-Trung Luu | 70d849d | 2015-05-11 16:57:08 -0700 | [diff] [blame] | 88 | }); |
| 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 Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 100 | moterm_file_->Read(1000, 0, mojo::files::Whence::FROM_CURRENT, |
Viet-Trung Luu | 70d849d | 2015-05-11 16:57:08 -0700 | [diff] [blame] | 101 | base::Bind(&MotermExampleAppView::OnInputFromPrompt, |
| 102 | weak_factory_.GetWeakPtr())); |
| 103 | } |
| 104 | void OnInputFromPrompt(mojo::files::Error error, |
| 105 | mojo::Array<uint8_t> bytes_read) { |
John Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 106 | if (error != mojo::files::Error::OK || !bytes_read) { |
Viet-Trung Luu | 70d849d | 2015-05-11 16:57:08 -0700 | [diff] [blame] | 107 | // 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 Luu | c5cfd31 | 2016-04-25 16:57:51 -0700 | [diff] [blame] | 133 | mojo::ConnectToService(dest_sp.get(), GetProxy(&dest_terminal_client)); |
Viet-Trung Luu | 70d849d | 2015-05-11 16:57:08 -0700 | [diff] [blame] | 134 | moterm_terminal_->ConnectToClient( |
Vardhan Mudunuru | c3575c4 | 2016-02-11 15:08:21 -0800 | [diff] [blame] | 135 | std::move(dest_terminal_client), true, |
Viet-Trung Luu | 70d849d | 2015-05-11 16:57:08 -0700 | [diff] [blame] | 136 | 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 Grossman | 87fe514 | 2015-10-02 10:11:43 -0700 | [diff] [blame] | 142 | DCHECK_EQ(error, mojo::files::Error::OK); |
Viet-Trung Luu | 70d849d | 2015-05-11 16:57:08 -0700 | [diff] [blame] | 143 | StartPrompt(false); |
| 144 | } |
| 145 | |
Viet-Trung Luu | 70d849d | 2015-05-11 16:57:08 -0700 | [diff] [blame] | 146 | mojo::Shell* const shell_; |
Jeff Brown | 5a846ea | 2016-01-26 15:53:07 -0800 | [diff] [blame] | 147 | mojo::ui::ViewProviderPtr moterm_view_provider_; |
Viet-Trung Luu | 70d849d | 2015-05-11 16:57:08 -0700 | [diff] [blame] | 148 | |
Viet-Trung Luu | 70d849d | 2015-05-11 16:57:08 -0700 | [diff] [blame] | 149 | 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 Brown | 83365b1 | 2016-02-10 11:08:14 -0800 | [diff] [blame] | 158 | class MotermExampleApp : public mojo::ui::ViewProviderApp { |
Viet-Trung Luu | 70d849d | 2015-05-11 16:57:08 -0700 | [diff] [blame] | 159 | public: |
Jeff Brown | 83365b1 | 2016-02-10 11:08:14 -0800 | [diff] [blame] | 160 | MotermExampleApp() {} |
Viet-Trung Luu | 70d849d | 2015-05-11 16:57:08 -0700 | [diff] [blame] | 161 | ~MotermExampleApp() override {} |
| 162 | |
Jeff Brown | 83365b1 | 2016-02-10 11:08:14 -0800 | [diff] [blame] | 163 | // |ViewProviderApp|: |
| 164 | void CreateView( |
| 165 | const std::string& connection_url, |
| 166 | mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request, |
Viet-Trung Luu | db06898 | 2016-05-24 13:15:55 -0700 | [diff] [blame] | 167 | mojo::InterfaceRequest<mojo::ServiceProvider> services) override { |
Viet-Trung Luu | 8f8c215 | 2016-05-31 13:11:00 -0700 | [diff] [blame] | 168 | new MotermExampleAppView(shell(), view_owner_request.Pass()); |
Jeff Brown | 83365b1 | 2016-02-10 11:08:14 -0800 | [diff] [blame] | 169 | } |
| 170 | |
Viet-Trung Luu | 70d849d | 2015-05-11 16:57:08 -0700 | [diff] [blame] | 171 | private: |
Viet-Trung Luu | 70d849d | 2015-05-11 16:57:08 -0700 | [diff] [blame] | 172 | DISALLOW_COPY_AND_ASSIGN(MotermExampleApp); |
| 173 | }; |
| 174 | |
| 175 | MojoResult MojoMain(MojoHandle application_request) { |
Viet-Trung Luu | 8f8c215 | 2016-05-31 13:11:00 -0700 | [diff] [blame] | 176 | mojo::ScopedChromiumInit init; |
| 177 | MotermExampleApp moterm_example_app; |
| 178 | return mojo::RunApplication(application_request, &moterm_example_app); |
Viet-Trung Luu | 70d849d | 2015-05-11 16:57:08 -0700 | [diff] [blame] | 179 | } |