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

Side by Side Diff: ios/web/webui/mojo_facade.mm

Issue 1956113002: [ios Mojo] iOS facade class for Mojo API. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Self review Created 4 years, 7 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 unified diff | Download patch
« no previous file with comments | « ios/web/webui/mojo_facade.h ('k') | ios/web/webui/mojo_facade_unittest.mm » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2016 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 #import "ios/web/webui/mojo_facade.h"
6
7 #import <Foundation/Foundation.h>
8
9 #include "base/ios/block_types.h"
10 #include "base/json/json_reader.h"
11 #include "base/json/json_writer.h"
12 #include "base/mac/bind_objc_block.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/values.h"
15 #import "ios/web/public/web_state/js/crw_js_injection_evaluator.h"
16 #include "ios/web/public/web_thread.h"
17 #include "mojo/public/cpp/system/core.h"
18 #include "services/shell/public/interfaces/interface_provider.mojom.h"
19
20 namespace web {
21
22 namespace {
23
24 // Wraps an integer into |base::Value| as |TYPE_INTEGER|.
25 template <typename IntegerT>
26 std::unique_ptr<base::Value> ValueFromInteger(IntegerT handle) {
27 return std::unique_ptr<base::Value>(
28 new base::FundamentalValue(static_cast<int>(handle)));
29 }
30
31 } // namespace
32
33 MojoFacade::MojoFacade(shell::mojom::InterfaceProvider* interface_provider,
34 id<CRWJSInjectionEvaluator> script_evaluator)
35 : interface_provider_(interface_provider),
36 script_evaluator_(script_evaluator) {
37 DCHECK_CURRENTLY_ON(WebThread::UI);
38 DCHECK(interface_provider_);
39 DCHECK(script_evaluator_);
40 }
41
42 MojoFacade::~MojoFacade() {
43 DCHECK_CURRENTLY_ON(WebThread::UI);
44 }
45
46 std::string MojoFacade::HandleMojoMessage(
47 const std::string& mojo_message_as_json) {
48 DCHECK_CURRENTLY_ON(WebThread::UI);
49 std::string name;
50 std::unique_ptr<base::DictionaryValue> args;
51 GetMessageNameAndArguments(mojo_message_as_json, &name, &args);
52
53 std::unique_ptr<base::Value> result;
54 if (name == "service_provider.connectToService") {
55 result = HandleServiceProviderConnectToService(args.get());
56 } else if (name == "core.close") {
57 result = HandleCoreClose(args.get());
58 } else if (name == "core.createMessagePipe") {
59 result = HandleCoreCreateMessagePipe(args.get());
60 } else if (name == "core.writeMessage") {
61 result = HandleCoreWriteMessage(args.get());
62 } else if (name == "core.readMessage") {
63 result = HandleCoreReadMessage(args.get());
64 } else if (name == "support.watch") {
65 result = HandleSupportWatch(args.get());
66 } else if (name == "support.cancelWatch") {
67 result = HandleSupportCancelWatch(args.get());
68 }
69
70 if (!result) {
71 return "";
72 }
73
74 std::string json_result;
75 base::JSONWriter::Write(*result, &json_result);
76 return json_result;
77 }
78
79 void MojoFacade::GetMessageNameAndArguments(
80 const std::string& mojo_message_as_json,
81 std::string* out_name,
82 std::unique_ptr<base::DictionaryValue>* out_args) {
83 int error_code = 0;
84 std::string error_message;
85 std::unique_ptr<base::Value> mojo_message_as_value(
86 base::JSONReader::ReadAndReturnError(mojo_message_as_json, false,
87 &error_code, &error_message));
88 CHECK(!error_code);
89 base::DictionaryValue* mojo_message = nullptr;
90 CHECK(mojo_message_as_value->GetAsDictionary(&mojo_message));
91
92 std::string name;
93 CHECK(mojo_message->GetString("name", &name));
94
95 base::DictionaryValue* args = nullptr;
96 CHECK(mojo_message->GetDictionary("args", &args));
97
98 *out_name = name;
99 *out_args = args->CreateDeepCopy();
100 }
101
102 std::unique_ptr<base::Value> MojoFacade::HandleServiceProviderConnectToService(
103 const base::DictionaryValue* args) {
104 const base::Value* service_name_as_value = nullptr;
105 CHECK(args->Get("serviceName", &service_name_as_value));
106
107 // By design service_provider.connectToService either succeeds or crashes, so
108 // check if service name is a valid string is intentionally omitted.
109 std::string service_name_as_string;
110 service_name_as_value->GetAsString(&service_name_as_string);
111
112 mojo::MessagePipe pipe;
113 interface_provider_->GetInterface(mojo::String::From(service_name_as_string),
114 std::move(pipe.handle0));
115
116 return ValueFromInteger(pipe.handle1.release().value());
117 }
118
119 std::unique_ptr<base::Value> MojoFacade::HandleCoreClose(
120 const base::DictionaryValue* args) {
121 int handle = 0;
122 CHECK(args->GetInteger("handle", &handle));
123
124 mojo::Handle(handle).Close();
125
126 return ValueFromInteger(MOJO_RESULT_OK);
127 }
128
129 std::unique_ptr<base::Value> MojoFacade::HandleCoreCreateMessagePipe(
130 base::DictionaryValue* args) {
131 const base::Value* options_as_value = nullptr;
132 CHECK(args->Get("optionsDict", &options_as_value));
133
134 if (options_as_value->IsType(base::Value::TYPE_DICTIONARY)) {
135 // Extract options when this codepath is hit.
Ken Rockot(use gerrit already) 2016/05/13 15:21:45 nit: Can you just CHECK that the dictionary is emp
Eugene But (OOO till 7-30) 2016/05/14 00:05:09 Done.
136 NOTIMPLEMENTED();
137 }
138
139 CHECK(options_as_value->IsType(base::Value::TYPE_NULL));
140
141 mojo::MessagePipe message_pipe;
142 std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue);
143 result->SetInteger("handle0", message_pipe.handle0.release().value());
144 result->SetInteger("handle1", message_pipe.handle1.release().value());
145 return std::unique_ptr<base::Value>(result.release());
146 }
147
148 std::unique_ptr<base::Value> MojoFacade::HandleCoreWriteMessage(
149 base::DictionaryValue* args) {
150 int handle = 0;
151 CHECK(args->GetInteger("handle", &handle));
152
153 base::ListValue* handles_list = nullptr;
154 CHECK(args->GetList("handles", &handles_list));
155
156 base::DictionaryValue* buffer = nullptr;
157 CHECK(args->GetDictionary("buffer", &buffer));
158
159 const base::Value* flags_as_value = nullptr;
160 CHECK(args->Get("flags", &flags_as_value));
161
162 int flags = MOJO_WRITE_MESSAGE_FLAG_NONE;
163 if (!flags_as_value->GetAsInteger(&flags)) {
164 flags = MOJO_WRITE_MESSAGE_FLAG_NONE;
165 }
166
167 std::vector<MojoHandle> handles(handles_list->GetSize());
168 for (size_t i = 0; i < handles_list->GetSize(); i++) {
169 int one_handle = 0;
170 handles_list->GetInteger(i, &one_handle);
171 handles[i] = one_handle;
172 }
173
174 std::vector<uint8_t> bytes(buffer->size());
175 for (size_t i = 0; i < buffer->size(); i++) {
176 int one_byte = 0;
177 buffer->GetInteger(base::IntToString(i), &one_byte);
178 bytes[i] = one_byte;
179 }
180
181 mojo::MessagePipeHandle message_pipe(static_cast<MojoHandle>(handle));
182 MojoResult result =
183 mojo::WriteMessageRaw(message_pipe, bytes.data(), bytes.size(),
184 handles.data(), handles.size(), flags);
185
186 return ValueFromInteger(result);
187 }
188
189 std::unique_ptr<base::Value> MojoFacade::HandleCoreReadMessage(
190 const base::DictionaryValue* args) {
191 const base::Value* handle_as_value = nullptr;
192 CHECK(args->Get("handle", &handle_as_value));
193 int handle_as_int = 0;
194 if (!handle_as_value->GetAsInteger(&handle_as_int)) {
195 handle_as_int = 0;
196 }
197
198 const base::Value* flags_as_value = nullptr;
199 CHECK(args->Get("flags", &flags_as_value));
200
201 int flags = MOJO_READ_MESSAGE_FLAG_NONE;
202 if (!flags_as_value->GetAsInteger(&flags)) {
203 flags = MOJO_READ_MESSAGE_FLAG_NONE;
204 }
205
206 uint32_t num_bytes = 0;
207 uint32_t num_handles = 0;
208 mojo::MessagePipeHandle handle(static_cast<MojoHandle>(handle_as_int));
209 MojoResult mojo_result = mojo::ReadMessageRaw(handle, nullptr, &num_bytes,
210 nullptr, &num_handles, flags);
211 std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue);
212
213 if (mojo_result == MOJO_RESULT_RESOURCE_EXHAUSTED) {
214 std::vector<uint8_t> bytes(num_bytes);
215 std::vector<MojoHandle> handles(num_handles);
216 mojo_result = mojo::ReadMessageRaw(handle, bytes.data(), &num_bytes,
217 handles.data(), &num_handles, flags);
218
219 base::ListValue* handles_list = new base::ListValue;
220 for (uint32_t i = 0; i < num_handles; i++) {
221 handles_list->AppendInteger(handles[i]);
222 }
223 result->Set("handles", std::unique_ptr<base::Value>(handles_list));
224
225 base::ListValue* buffer = new base::ListValue;
226 for (uint32_t i = 0; i < num_bytes; i++) {
227 buffer->AppendInteger(bytes[i]);
228 }
229 result->Set("buffer", std::unique_ptr<base::Value>(buffer));
230 }
231 result->SetInteger("result", mojo_result);
232
233 return std::unique_ptr<base::Value>(result.release());
234 }
235
236 std::unique_ptr<base::Value> MojoFacade::HandleSupportWatch(
237 const base::DictionaryValue* args) {
238 int handle = 0;
239 CHECK(args->GetInteger("handle", &handle));
240 int signals = 0;
241 CHECK(args->GetInteger("signals", &signals));
242 int callback_id;
243 CHECK(args->GetInteger("callbackId", &callback_id));
244
245 mojo::Watcher::ReadyCallback callback = base::BindBlock(^(MojoResult result) {
246 NSString* script =
247 [NSString stringWithFormat:@"__crWeb.mojo.signalWatch(%d, %d)",
248 callback_id, result];
249 [script_evaluator_ executeJavaScript:script completionHandler:nil];
250 });
251
252 mojo::Watcher& watcher = watchers_[++last_watch_id_];
253 watcher.Start(static_cast<mojo::Handle>(handle), signals, callback);
254 return ValueFromInteger(last_watch_id_);
255 }
256
257 std::unique_ptr<base::Value> MojoFacade::HandleSupportCancelWatch(
258 const base::DictionaryValue* args) {
259 int watch_id = 0;
260 CHECK(args->GetInteger("watchId", &watch_id));
261 auto watch_it = watchers_.find(watch_id);
262 if (watch_it != watchers_.end()) {
263 watch_it->second.Cancel();
Ken Rockot(use gerrit already) 2016/05/13 15:21:45 nit: No need to call this explicitly, the Watcher'
Eugene But (OOO till 7-30) 2016/05/14 00:05:09 Cool. Done.
264 watchers_.erase(watch_it);
265 }
266 return nullptr;
267 }
268
269 } // namespace web
OLDNEW
« no previous file with comments | « ios/web/webui/mojo_facade.h ('k') | ios/web/webui/mojo_facade_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698