Chromium Code Reviews| 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, handle1; |
|
Eugene But (OOO till 7-30)
2017/06/24 01:09:51
nit: Per Style Guide, please initialize local vari
yzshen1
2017/06/26 20:09:59
Done.
| |
| 109 CreateMessagePipe(&handle0, &handle1); | |
| 110 | |
| 111 // Pass handle0 as interface request. | |
| 81 NSDictionary* connect = @{ | 112 NSDictionary* connect = @{ |
| 82 @"name" : @"interface_provider.getInterface", | 113 @"name" : @"Mojo.bindInterface", |
| 83 @"args" : @{ | 114 @"args" : @{ |
| 84 @"interfaceName" : @"::TestUIHandlerMojo", | 115 @"interfaceName" : @"::TestUIHandlerMojo", |
| 116 @"requestHandle" : @(handle0), | |
| 85 }, | 117 }, |
| 86 }; | 118 }; |
| 87 | 119 |
| 88 std::string handle_as_string = facade()->HandleMojoMessage(GetJson(connect)); | 120 std::string handle_as_string = facade()->HandleMojoMessage(GetJson(connect)); |
| 89 EXPECT_FALSE(handle_as_string.empty()); | 121 EXPECT_TRUE(handle_as_string.empty()); |
| 90 int handle = 0; | |
| 91 EXPECT_TRUE(base::StringToInt(handle_as_string, &handle)); | |
| 92 | 122 |
| 93 // Close the handle. | 123 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 } | 124 } |
| 106 | 125 |
| 107 // Tests creating a message pipe without options. | 126 // Tests creating a message pipe. |
| 108 TEST_F(MojoFacadeTest, CreateMessagePipeWithoutOptions) { | 127 TEST_F(MojoFacadeTest, CreateMessagePipe) { |
| 109 // Create a message pipe. | 128 uint32_t handle0, handle1; |
| 110 NSDictionary* create = @{ | 129 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 | 130 |
| 118 // Verify handles. | 131 CloseHandle(handle0); |
| 119 EXPECT_FALSE(response_as_string.empty()); | 132 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 } | 133 } |
| 153 | 134 |
| 154 // Tests watching the pipe. | 135 // Tests watching the pipe. |
| 155 TEST_F(MojoFacadeTest, Watch) { | 136 TEST_F(MojoFacadeTest, Watch) { |
| 156 // Create a message pipe. | 137 uint32_t handle0, handle1; |
| 157 NSDictionary* create = @{ | 138 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 | 139 |
| 174 // Start watching one end of the pipe. | 140 // Start watching one end of the pipe. |
| 175 int callback_id = 99; | 141 int callback_id = 99; |
| 176 NSDictionary* watch = @{ | 142 NSDictionary* watch = @{ |
| 177 @"name" : @"support.watch", | 143 @"name" : @"MojoHandle.watch", |
| 178 @"args" : @{ | 144 @"args" : @{ |
| 179 @"handle" : handle0, | 145 @"handle" : @(handle0), |
| 180 @"signals" : @(MOJO_HANDLE_SIGNAL_READABLE), | 146 @"signals" : @(MOJO_HANDLE_SIGNAL_READABLE), |
| 181 @"callbackId" : @(callback_id), | 147 @"callbackId" : @(callback_id), |
| 182 }, | 148 }, |
| 183 }; | 149 }; |
| 184 std::string watch_id_as_string = facade()->HandleMojoMessage(GetJson(watch)); | 150 std::string watch_id_as_string = facade()->HandleMojoMessage(GetJson(watch)); |
| 185 EXPECT_FALSE(watch_id_as_string.empty()); | 151 EXPECT_FALSE(watch_id_as_string.empty()); |
| 186 int watch_id = 0; | 152 int watch_id = 0; |
| 187 EXPECT_TRUE(base::StringToInt(watch_id_as_string, &watch_id)); | 153 EXPECT_TRUE(base::StringToInt(watch_id_as_string, &watch_id)); |
| 188 | 154 |
| 189 // Start waiting for the watch callback. | 155 // Start waiting for the watch callback. |
| 190 __block bool callback_received = false; | 156 __block bool callback_received = false; |
| 191 NSString* expected_script = | 157 NSString* expected_script = |
| 192 [NSString stringWithFormat:@"__crWeb.mojo.signalWatch(%d, %d)", | 158 [NSString stringWithFormat: |
| 193 callback_id, MOJO_RESULT_OK]; | 159 @"Mojo.internal.watchCallbacksHolder.callCallback(%d, %d)", |
| 160 callback_id, MOJO_RESULT_OK]; | |
| 194 [[[evaluator() expect] andDo:^(NSInvocation*) { | 161 [[[evaluator() expect] andDo:^(NSInvocation*) { |
| 195 callback_received = true; | 162 callback_received = true; |
| 196 | 163 |
| 197 // Cancel the watch immediately to ensure there are no additional | 164 // Cancel the watch immediately to ensure there are no additional |
| 198 // notifications. | 165 // notifications. |
| 199 NSDictionary* cancel_watch = @{ | 166 NSDictionary* cancel_watch = @{ |
| 200 @"name" : @"support.cancelWatch", | 167 @"name" : @"MojoWatcher.cancel", |
| 201 @"args" : @{ | 168 @"args" : @{ |
| 202 @"watchId" : @(watch_id), | 169 @"watchId" : @(watch_id), |
| 203 }, | 170 }, |
| 204 }; | 171 }; |
| 205 std::string result_as_string = | 172 std::string result_as_string = |
| 206 facade()->HandleMojoMessage(GetJson(cancel_watch)); | 173 facade()->HandleMojoMessage(GetJson(cancel_watch)); |
| 207 EXPECT_TRUE(result_as_string.empty()); | 174 EXPECT_TRUE(result_as_string.empty()); |
| 208 }] executeJavaScript:expected_script completionHandler:nil]; | 175 }] executeJavaScript:expected_script completionHandler:nil]; |
| 209 | 176 |
| 210 // Write to the other end of the pipe. | 177 // Write to the other end of the pipe. |
| 211 NSDictionary* write = @{ | 178 NSDictionary* write = @{ |
| 212 @"name" : @"core.writeMessage", | 179 @"name" : @"MojoHandle.writeMessage", |
| 213 @"args" : @{ | 180 @"args" : |
| 214 @"handle" : handle1, | 181 @{@"handle" : @(handle1), @"handles" : @[], @"buffer" : @{@"0" : @0}}, |
| 215 @"handles" : @[], | |
| 216 @"flags" : @(MOJO_WRITE_MESSAGE_FLAG_NONE), | |
| 217 @"buffer" : @{@"0" : @0} | |
| 218 }, | |
| 219 }; | 182 }; |
| 220 std::string result_as_string = facade()->HandleMojoMessage(GetJson(write)); | 183 std::string result_as_string = facade()->HandleMojoMessage(GetJson(write)); |
| 221 EXPECT_FALSE(result_as_string.empty()); | 184 EXPECT_FALSE(result_as_string.empty()); |
| 222 int result = 0; | 185 int result = 0; |
| 223 EXPECT_TRUE(base::StringToInt(result_as_string, &result)); | 186 EXPECT_TRUE(base::StringToInt(result_as_string, &result)); |
| 224 EXPECT_EQ(MOJO_RESULT_OK, static_cast<MojoResult>(result)); | 187 EXPECT_EQ(MOJO_RESULT_OK, static_cast<MojoResult>(result)); |
| 225 | 188 |
| 226 base::test::ios::WaitUntilCondition( | 189 base::test::ios::WaitUntilCondition( |
| 227 ^{ | 190 ^{ |
| 228 return callback_received; | 191 return callback_received; |
| 229 }, | 192 }, |
| 230 true, base::TimeDelta()); | 193 true, base::TimeDelta()); |
| 194 | |
| 195 CloseHandle(handle0); | |
| 196 CloseHandle(handle1); | |
| 231 } | 197 } |
| 232 | 198 |
| 233 // Tests reading the message from the pipe. | 199 // Tests reading the message from the pipe. |
| 234 TEST_F(MojoFacadeTest, ReadWrite) { | 200 TEST_F(MojoFacadeTest, ReadWrite) { |
| 235 // Create a message pipe. | 201 uint32_t handle0, handle1; |
| 236 NSDictionary* create = @{ | 202 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 | 203 |
| 253 // Write to the other end of the pipe. | 204 // Write to the other end of the pipe. |
| 254 NSDictionary* write = @{ | 205 NSDictionary* write = @{ |
| 255 @"name" : @"core.writeMessage", | 206 @"name" : @"MojoHandle.writeMessage", |
| 256 @"args" : @{ | 207 @"args" : @{ |
| 257 @"handle" : handle1, | 208 @"handle" : @(handle1), |
| 258 @"handles" : @[], | 209 @"handles" : @[], |
| 259 @"flags" : @(MOJO_WRITE_MESSAGE_FLAG_NONE), | |
| 260 @"buffer" : @{@"0" : @9, @"1" : @2, @"2" : @2008} | 210 @"buffer" : @{@"0" : @9, @"1" : @2, @"2" : @2008} |
| 261 }, | 211 }, |
| 262 }; | 212 }; |
| 263 std::string result_as_string = facade()->HandleMojoMessage(GetJson(write)); | 213 std::string result_as_string = facade()->HandleMojoMessage(GetJson(write)); |
| 264 EXPECT_FALSE(result_as_string.empty()); | 214 EXPECT_FALSE(result_as_string.empty()); |
| 265 int result = 0; | 215 int result = 0; |
| 266 EXPECT_TRUE(base::StringToInt(result_as_string, &result)); | 216 EXPECT_TRUE(base::StringToInt(result_as_string, &result)); |
| 267 EXPECT_EQ(MOJO_RESULT_OK, static_cast<MojoResult>(result)); | 217 EXPECT_EQ(MOJO_RESULT_OK, static_cast<MojoResult>(result)); |
| 268 | 218 |
| 269 // Read the message from the pipe. | 219 // Read the message from the pipe. |
| 270 NSDictionary* read = @{ | 220 NSDictionary* read = @{ |
| 271 @"name" : @"core.readMessage", | 221 @"name" : @"MojoHandle.readMessage", |
| 272 @"args" : @{ | 222 @"args" : @{ |
| 273 @"handle" : handle0, | 223 @"handle" : @(handle0), |
| 274 @"flags" : @(MOJO_READ_MESSAGE_FLAG_NONE), | |
| 275 }, | 224 }, |
| 276 }; | 225 }; |
| 277 NSDictionary* message = GetObject(facade()->HandleMojoMessage(GetJson(read))); | 226 NSDictionary* message = GetObject(facade()->HandleMojoMessage(GetJson(read))); |
| 278 EXPECT_TRUE([message isKindOfClass:[NSDictionary class]]); | 227 EXPECT_TRUE([message isKindOfClass:[NSDictionary class]]); |
| 279 EXPECT_TRUE(message); | 228 EXPECT_TRUE(message); |
| 280 NSArray* expected_message = @[ @9, @2, @216 ]; // 2008 does not fit 8-bit. | 229 NSArray* expected_message = @[ @9, @2, @216 ]; // 2008 does not fit 8-bit. |
| 281 EXPECT_NSEQ(expected_message, message[@"buffer"]); | 230 EXPECT_NSEQ(expected_message, message[@"buffer"]); |
| 282 EXPECT_FALSE([message[@"handles"] count]); | 231 EXPECT_FALSE([message[@"handles"] count]); |
| 283 EXPECT_EQ(MOJO_RESULT_OK, [message[@"result"] unsignedIntValue]); | 232 EXPECT_EQ(MOJO_RESULT_OK, [message[@"result"] unsignedIntValue]); |
| 233 | |
| 234 CloseHandle(handle0); | |
| 235 CloseHandle(handle1); | |
| 284 } | 236 } |
| 285 | 237 |
| 286 } // namespace web | 238 } // namespace web |
| OLD | NEW |