OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #import "ios/web/webui/mojo_facade.h" | 5 #import "ios/web/webui/mojo_facade.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 | 8 |
9 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
10 #include "base/strings/sys_string_conversions.h" | 10 #include "base/strings/sys_string_conversions.h" |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 evaluator_ = | 58 evaluator_ = |
59 [OCMockObject mockForProtocol:@protocol(CRWJSInjectionEvaluator)]; | 59 [OCMockObject mockForProtocol:@protocol(CRWJSInjectionEvaluator)]; |
60 facade_ = base::MakeUnique<MojoFacade>( | 60 facade_ = base::MakeUnique<MojoFacade>( |
61 interface_provider_.get(), | 61 interface_provider_.get(), |
62 static_cast<id<CRWJSInjectionEvaluator>>(evaluator_)); | 62 static_cast<id<CRWJSInjectionEvaluator>>(evaluator_)); |
63 } | 63 } |
64 | 64 |
65 OCMockObject* evaluator() { return evaluator_; } | 65 OCMockObject* evaluator() { return evaluator_; } |
66 MojoFacade* facade() { return facade_.get(); } | 66 MojoFacade* facade() { return facade_.get(); } |
67 | 67 |
| 68 void CreateMessagePipe(uint32_t* handle0, uint32_t* handle1) { |
| 69 NSDictionary* create = @{ |
| 70 @"name" : @"Mojo.createMessagePipe", |
| 71 @"args" : @{}, |
| 72 }; |
| 73 std::string response_as_string = |
| 74 facade()->HandleMojoMessage(GetJson(create)); |
| 75 |
| 76 // Verify handles. |
| 77 ASSERT_FALSE(response_as_string.empty()); |
| 78 NSDictionary* response_as_dict = GetObject(response_as_string); |
| 79 ASSERT_TRUE([response_as_dict isKindOfClass:[NSDictionary class]]); |
| 80 ASSERT_EQ(MOJO_RESULT_OK, [response_as_dict[@"result"] unsignedIntValue]); |
| 81 *handle0 = [response_as_dict[@"handle0"] unsignedIntValue]; |
| 82 *handle1 = [response_as_dict[@"handle1"] unsignedIntValue]; |
| 83 } |
| 84 |
| 85 void CloseHandle(uint32_t handle) { |
| 86 NSDictionary* close = @{ |
| 87 @"name" : @"MojoHandle.close", |
| 88 @"args" : @{ |
| 89 @"handle" : @(handle), |
| 90 }, |
| 91 }; |
| 92 std::string result = facade()->HandleMojoMessage(GetJson(close)); |
| 93 EXPECT_TRUE(result.empty()); |
| 94 } |
| 95 |
68 private: | 96 private: |
69 void BindTestUIHandlerMojoRequest( | 97 void BindTestUIHandlerMojoRequest( |
70 const service_manager::BindSourceInfo& source_info, | 98 const service_manager::BindSourceInfo& source_info, |
71 TestUIHandlerMojoRequest request) {} | 99 TestUIHandlerMojoRequest request) {} |
72 | 100 |
73 std::unique_ptr<WebStateInterfaceProvider> interface_provider_; | 101 std::unique_ptr<WebStateInterfaceProvider> interface_provider_; |
74 OCMockObject* evaluator_; | 102 OCMockObject* evaluator_; |
75 std::unique_ptr<MojoFacade> facade_; | 103 std::unique_ptr<MojoFacade> facade_; |
76 }; | 104 }; |
77 | 105 |
78 // Tests connecting to existing interface and closing the handle. | 106 // Tests binding an interface. |
79 TEST_F(MojoFacadeTest, GetInterfaceAndCloseHandle) { | 107 TEST_F(MojoFacadeTest, BindInterface) { |
80 // Bind to the interface. | 108 uint32_t handle0 = 0; |
| 109 uint32_t handle1 = 0; |
| 110 CreateMessagePipe(&handle0, &handle1); |
| 111 |
| 112 // Pass handle0 as interface request. |
81 NSDictionary* connect = @{ | 113 NSDictionary* connect = @{ |
82 @"name" : @"interface_provider.getInterface", | 114 @"name" : @"Mojo.bindInterface", |
83 @"args" : @{ | 115 @"args" : @{ |
84 @"interfaceName" : @"::TestUIHandlerMojo", | 116 @"interfaceName" : @"::TestUIHandlerMojo", |
| 117 @"requestHandle" : @(handle0), |
85 }, | 118 }, |
86 }; | 119 }; |
87 | 120 |
88 std::string handle_as_string = facade()->HandleMojoMessage(GetJson(connect)); | 121 std::string handle_as_string = facade()->HandleMojoMessage(GetJson(connect)); |
89 EXPECT_FALSE(handle_as_string.empty()); | 122 EXPECT_TRUE(handle_as_string.empty()); |
90 int handle = 0; | |
91 EXPECT_TRUE(base::StringToInt(handle_as_string, &handle)); | |
92 | 123 |
93 // Close the handle. | 124 CloseHandle(handle1); |
94 NSDictionary* close = @{ | |
95 @"name" : @"core.close", | |
96 @"args" : @{ | |
97 @"handle" : @(handle), | |
98 }, | |
99 }; | |
100 std::string result_as_string = facade()->HandleMojoMessage(GetJson(close)); | |
101 EXPECT_FALSE(result_as_string.empty()); | |
102 int result = 0; | |
103 EXPECT_TRUE(base::StringToInt(result_as_string, &result)); | |
104 EXPECT_EQ(MOJO_RESULT_OK, static_cast<MojoResult>(result)); | |
105 } | 125 } |
106 | 126 |
107 // Tests creating a message pipe without options. | 127 // Tests creating a message pipe. |
108 TEST_F(MojoFacadeTest, CreateMessagePipeWithoutOptions) { | 128 TEST_F(MojoFacadeTest, CreateMessagePipe) { |
109 // Create a message pipe. | 129 uint32_t handle0, handle1; |
110 NSDictionary* create = @{ | 130 CreateMessagePipe(&handle0, &handle1); |
111 @"name" : @"core.createMessagePipe", | |
112 @"args" : @{ | |
113 @"optionsDict" : [NSNull null], | |
114 }, | |
115 }; | |
116 std::string response_as_string = facade()->HandleMojoMessage(GetJson(create)); | |
117 | 131 |
118 // Verify handles. | 132 CloseHandle(handle0); |
119 EXPECT_FALSE(response_as_string.empty()); | 133 CloseHandle(handle1); |
120 NSDictionary* response_as_dict = GetObject(response_as_string); | |
121 EXPECT_TRUE([response_as_dict isKindOfClass:[NSDictionary class]]); | |
122 id handle0 = response_as_dict[@"handle0"]; | |
123 EXPECT_TRUE(handle0); | |
124 id handle1 = response_as_dict[@"handle1"]; | |
125 EXPECT_TRUE(handle1); | |
126 | |
127 // Close handle0. | |
128 NSDictionary* close0 = @{ | |
129 @"name" : @"core.close", | |
130 @"args" : @{ | |
131 @"handle" : handle0, | |
132 }, | |
133 }; | |
134 std::string result0_as_string = facade()->HandleMojoMessage(GetJson(close0)); | |
135 EXPECT_FALSE(result0_as_string.empty()); | |
136 int result0 = 0; | |
137 EXPECT_TRUE(base::StringToInt(result0_as_string, &result0)); | |
138 EXPECT_EQ(MOJO_RESULT_OK, static_cast<MojoResult>(result0)); | |
139 | |
140 // Close handle1. | |
141 NSDictionary* close1 = @{ | |
142 @"name" : @"core.close", | |
143 @"args" : @{ | |
144 @"handle" : handle1, | |
145 }, | |
146 }; | |
147 std::string result1_as_string = facade()->HandleMojoMessage(GetJson(close1)); | |
148 EXPECT_FALSE(result1_as_string.empty()); | |
149 int result1 = 0; | |
150 EXPECT_TRUE(base::StringToInt(result1_as_string, &result1)); | |
151 EXPECT_EQ(MOJO_RESULT_OK, static_cast<MojoResult>(result1)); | |
152 } | 134 } |
153 | 135 |
154 // Tests watching the pipe. | 136 // Tests watching the pipe. |
155 TEST_F(MojoFacadeTest, Watch) { | 137 TEST_F(MojoFacadeTest, Watch) { |
156 // Create a message pipe. | 138 uint32_t handle0, handle1; |
157 NSDictionary* create = @{ | 139 CreateMessagePipe(&handle0, &handle1); |
158 @"name" : @"core.createMessagePipe", | |
159 @"args" : @{ | |
160 @"optionsDict" : [NSNull null], | |
161 }, | |
162 }; | |
163 std::string response_as_string = facade()->HandleMojoMessage(GetJson(create)); | |
164 | |
165 // Verify handles. | |
166 EXPECT_FALSE(response_as_string.empty()); | |
167 NSDictionary* response_as_dict = GetObject(response_as_string); | |
168 EXPECT_TRUE([response_as_dict isKindOfClass:[NSDictionary class]]); | |
169 id handle0 = response_as_dict[@"handle0"]; | |
170 EXPECT_TRUE(handle0); | |
171 id handle1 = response_as_dict[@"handle1"]; | |
172 EXPECT_TRUE(handle1); | |
173 | 140 |
174 // Start watching one end of the pipe. | 141 // Start watching one end of the pipe. |
175 int callback_id = 99; | 142 int callback_id = 99; |
176 NSDictionary* watch = @{ | 143 NSDictionary* watch = @{ |
177 @"name" : @"support.watch", | 144 @"name" : @"MojoHandle.watch", |
178 @"args" : @{ | 145 @"args" : @{ |
179 @"handle" : handle0, | 146 @"handle" : @(handle0), |
180 @"signals" : @(MOJO_HANDLE_SIGNAL_READABLE), | 147 @"signals" : @(MOJO_HANDLE_SIGNAL_READABLE), |
181 @"callbackId" : @(callback_id), | 148 @"callbackId" : @(callback_id), |
182 }, | 149 }, |
183 }; | 150 }; |
184 std::string watch_id_as_string = facade()->HandleMojoMessage(GetJson(watch)); | 151 std::string watch_id_as_string = facade()->HandleMojoMessage(GetJson(watch)); |
185 EXPECT_FALSE(watch_id_as_string.empty()); | 152 EXPECT_FALSE(watch_id_as_string.empty()); |
186 int watch_id = 0; | 153 int watch_id = 0; |
187 EXPECT_TRUE(base::StringToInt(watch_id_as_string, &watch_id)); | 154 EXPECT_TRUE(base::StringToInt(watch_id_as_string, &watch_id)); |
188 | 155 |
189 // Start waiting for the watch callback. | 156 // Start waiting for the watch callback. |
190 __block bool callback_received = false; | 157 __block bool callback_received = false; |
191 NSString* expected_script = | 158 NSString* expected_script = |
192 [NSString stringWithFormat:@"__crWeb.mojo.signalWatch(%d, %d)", | 159 [NSString stringWithFormat: |
193 callback_id, MOJO_RESULT_OK]; | 160 @"Mojo.internal.watchCallbacksHolder.callCallback(%d, %d)", |
| 161 callback_id, MOJO_RESULT_OK]; |
194 [[[evaluator() expect] andDo:^(NSInvocation*) { | 162 [[[evaluator() expect] andDo:^(NSInvocation*) { |
195 callback_received = true; | 163 callback_received = true; |
196 | 164 |
197 // Cancel the watch immediately to ensure there are no additional | 165 // Cancel the watch immediately to ensure there are no additional |
198 // notifications. | 166 // notifications. |
199 NSDictionary* cancel_watch = @{ | 167 NSDictionary* cancel_watch = @{ |
200 @"name" : @"support.cancelWatch", | 168 @"name" : @"MojoWatcher.cancel", |
201 @"args" : @{ | 169 @"args" : @{ |
202 @"watchId" : @(watch_id), | 170 @"watchId" : @(watch_id), |
203 }, | 171 }, |
204 }; | 172 }; |
205 std::string result_as_string = | 173 std::string result_as_string = |
206 facade()->HandleMojoMessage(GetJson(cancel_watch)); | 174 facade()->HandleMojoMessage(GetJson(cancel_watch)); |
207 EXPECT_TRUE(result_as_string.empty()); | 175 EXPECT_TRUE(result_as_string.empty()); |
208 }] executeJavaScript:expected_script completionHandler:nil]; | 176 }] executeJavaScript:expected_script completionHandler:nil]; |
209 | 177 |
210 // Write to the other end of the pipe. | 178 // Write to the other end of the pipe. |
211 NSDictionary* write = @{ | 179 NSDictionary* write = @{ |
212 @"name" : @"core.writeMessage", | 180 @"name" : @"MojoHandle.writeMessage", |
213 @"args" : @{ | 181 @"args" : |
214 @"handle" : handle1, | 182 @{@"handle" : @(handle1), @"handles" : @[], @"buffer" : @{@"0" : @0}}, |
215 @"handles" : @[], | |
216 @"flags" : @(MOJO_WRITE_MESSAGE_FLAG_NONE), | |
217 @"buffer" : @{@"0" : @0} | |
218 }, | |
219 }; | 183 }; |
220 std::string result_as_string = facade()->HandleMojoMessage(GetJson(write)); | 184 std::string result_as_string = facade()->HandleMojoMessage(GetJson(write)); |
221 EXPECT_FALSE(result_as_string.empty()); | 185 EXPECT_FALSE(result_as_string.empty()); |
222 int result = 0; | 186 int result = 0; |
223 EXPECT_TRUE(base::StringToInt(result_as_string, &result)); | 187 EXPECT_TRUE(base::StringToInt(result_as_string, &result)); |
224 EXPECT_EQ(MOJO_RESULT_OK, static_cast<MojoResult>(result)); | 188 EXPECT_EQ(MOJO_RESULT_OK, static_cast<MojoResult>(result)); |
225 | 189 |
226 base::test::ios::WaitUntilCondition( | 190 base::test::ios::WaitUntilCondition( |
227 ^{ | 191 ^{ |
228 return callback_received; | 192 return callback_received; |
229 }, | 193 }, |
230 true, base::TimeDelta()); | 194 true, base::TimeDelta()); |
| 195 |
| 196 CloseHandle(handle0); |
| 197 CloseHandle(handle1); |
231 } | 198 } |
232 | 199 |
233 // Tests reading the message from the pipe. | 200 // Tests reading the message from the pipe. |
234 TEST_F(MojoFacadeTest, ReadWrite) { | 201 TEST_F(MojoFacadeTest, ReadWrite) { |
235 // Create a message pipe. | 202 uint32_t handle0, handle1; |
236 NSDictionary* create = @{ | 203 CreateMessagePipe(&handle0, &handle1); |
237 @"name" : @"core.createMessagePipe", | |
238 @"args" : @{ | |
239 @"optionsDict" : [NSNull null], | |
240 }, | |
241 }; | |
242 std::string response_as_string = facade()->HandleMojoMessage(GetJson(create)); | |
243 | |
244 // Verify handles. | |
245 EXPECT_FALSE(response_as_string.empty()); | |
246 NSDictionary* response_as_dict = GetObject(response_as_string); | |
247 EXPECT_TRUE([response_as_dict isKindOfClass:[NSDictionary class]]); | |
248 id handle0 = response_as_dict[@"handle0"]; | |
249 EXPECT_TRUE(handle0); | |
250 id handle1 = response_as_dict[@"handle1"]; | |
251 EXPECT_TRUE(handle1); | |
252 | 204 |
253 // Write to the other end of the pipe. | 205 // Write to the other end of the pipe. |
254 NSDictionary* write = @{ | 206 NSDictionary* write = @{ |
255 @"name" : @"core.writeMessage", | 207 @"name" : @"MojoHandle.writeMessage", |
256 @"args" : @{ | 208 @"args" : @{ |
257 @"handle" : handle1, | 209 @"handle" : @(handle1), |
258 @"handles" : @[], | 210 @"handles" : @[], |
259 @"flags" : @(MOJO_WRITE_MESSAGE_FLAG_NONE), | |
260 @"buffer" : @{@"0" : @9, @"1" : @2, @"2" : @2008} | 211 @"buffer" : @{@"0" : @9, @"1" : @2, @"2" : @2008} |
261 }, | 212 }, |
262 }; | 213 }; |
263 std::string result_as_string = facade()->HandleMojoMessage(GetJson(write)); | 214 std::string result_as_string = facade()->HandleMojoMessage(GetJson(write)); |
264 EXPECT_FALSE(result_as_string.empty()); | 215 EXPECT_FALSE(result_as_string.empty()); |
265 int result = 0; | 216 int result = 0; |
266 EXPECT_TRUE(base::StringToInt(result_as_string, &result)); | 217 EXPECT_TRUE(base::StringToInt(result_as_string, &result)); |
267 EXPECT_EQ(MOJO_RESULT_OK, static_cast<MojoResult>(result)); | 218 EXPECT_EQ(MOJO_RESULT_OK, static_cast<MojoResult>(result)); |
268 | 219 |
269 // Read the message from the pipe. | 220 // Read the message from the pipe. |
270 NSDictionary* read = @{ | 221 NSDictionary* read = @{ |
271 @"name" : @"core.readMessage", | 222 @"name" : @"MojoHandle.readMessage", |
272 @"args" : @{ | 223 @"args" : @{ |
273 @"handle" : handle0, | 224 @"handle" : @(handle0), |
274 @"flags" : @(MOJO_READ_MESSAGE_FLAG_NONE), | |
275 }, | 225 }, |
276 }; | 226 }; |
277 NSDictionary* message = GetObject(facade()->HandleMojoMessage(GetJson(read))); | 227 NSDictionary* message = GetObject(facade()->HandleMojoMessage(GetJson(read))); |
278 EXPECT_TRUE([message isKindOfClass:[NSDictionary class]]); | 228 EXPECT_TRUE([message isKindOfClass:[NSDictionary class]]); |
279 EXPECT_TRUE(message); | 229 EXPECT_TRUE(message); |
280 NSArray* expected_message = @[ @9, @2, @216 ]; // 2008 does not fit 8-bit. | 230 NSArray* expected_message = @[ @9, @2, @216 ]; // 2008 does not fit 8-bit. |
281 EXPECT_NSEQ(expected_message, message[@"buffer"]); | 231 EXPECT_NSEQ(expected_message, message[@"buffer"]); |
282 EXPECT_FALSE([message[@"handles"] count]); | 232 EXPECT_FALSE([message[@"handles"] count]); |
283 EXPECT_EQ(MOJO_RESULT_OK, [message[@"result"] unsignedIntValue]); | 233 EXPECT_EQ(MOJO_RESULT_OK, [message[@"result"] unsignedIntValue]); |
| 234 |
| 235 CloseHandle(handle0); |
| 236 CloseHandle(handle1); |
284 } | 237 } |
285 | 238 |
286 } // namespace web | 239 } // namespace web |
OLD | NEW |