1 // Copyright 2014 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.
6 #include "base/command_line.h"
7 #include "base/files/file_path.h"
8 #include "chrome/browser/extensions/extension_apitest.h"
9 #include "chrome/browser/extensions/extension_function_test_utils.h"
10 #include "chrome/browser/extensions/extension_service.h"
11 #include "chrome/browser/ui/browser.h"
12 #include "content/public/browser/browser_thread.h"
13 #include "extensions/browser/api/cast_channel/cast_channel_api.h"
14 #include "extensions/browser/api/cast_channel/cast_socket.h"
15 #include "extensions/browser/api/cast_channel/logger.h"
16 #include "extensions/common/api/cast_channel.h"
17 #include "extensions/common/switches.h"
18 #include "extensions/common/test_util.h"
19 #include "extensions/test/result_catcher.h"
20 #include "net/base/capturing_net_log.h"
21 #include "net/base/completion_callback.h"
22 #include "net/base/net_errors.h"
23 #include "testing/gmock/include/gmock/gmock.h"
24 #include "testing/gmock_mutant.h"
26 // TODO(mfoltz): Mock out the ApiResourceManager to resolve threading issues
27 // (crbug.com/398242) and simulate unloading of the extension.
29 namespace cast_channel
= extensions::core_api::cast_channel
;
30 using cast_channel::CastSocket
;
31 using cast_channel::ChannelError
;
32 using cast_channel::ErrorInfo
;
33 using cast_channel::Logger
;
34 using cast_channel::MessageInfo
;
35 using cast_channel::ReadyState
;
36 using extensions::Extension
;
38 namespace utils
= extension_function_test_utils
;
42 using ::testing::DoAll
;
43 using ::testing::Invoke
;
44 using ::testing::InSequence
;
45 using ::testing::Return
;
49 const char kTestExtensionId
[] = "ddchlicdkolnonkihahngkmmmjnjlkkf";
50 const int64 kTimeoutMs
= 10000;
52 static void FillMessageInfo(MessageInfo
* message_info
,
53 const std::string
& message
) {
54 message_info
->namespace_
= "foo";
55 message_info
->source_id
= "src";
56 message_info
->destination_id
= "dest";
57 message_info
->data
.reset(new base::StringValue(message
));
60 ACTION_TEMPLATE(InvokeCompletionCallback
,
61 HAS_1_TEMPLATE_PARAMS(int, k
),
62 AND_1_VALUE_PARAMS(result
)) {
63 ::std::tr1::get
<k
>(args
).Run(result
);
66 ACTION_P2(InvokeDelegateOnError
, api_test
, api
) {
67 api_test
->CallOnError(api
);
70 class MockCastSocket
: public CastSocket
{
72 explicit MockCastSocket(CastSocket::Delegate
* delegate
,
73 net::IPEndPoint ip_endpoint
,
75 const scoped_refptr
<Logger
>& logger
)
76 : CastSocket(kTestExtensionId
,
78 cast_channel::CHANNEL_AUTH_TYPE_SSL
,
81 base::TimeDelta::FromMilliseconds(kTimeoutMs
),
83 virtual ~MockCastSocket() {}
85 MOCK_METHOD1(Connect
, void(const net::CompletionCallback
& callback
));
86 MOCK_METHOD2(SendMessage
, void(const MessageInfo
& message
,
87 const net::CompletionCallback
& callback
));
88 MOCK_METHOD1(Close
, void(const net::CompletionCallback
& callback
));
89 MOCK_CONST_METHOD0(ready_state
, cast_channel::ReadyState());
90 MOCK_CONST_METHOD0(error_state
, cast_channel::ChannelError());
95 class CastChannelAPITest
: public ExtensionApiTest
{
97 CastChannelAPITest() {}
99 void SetUpCommandLine(CommandLine
* command_line
) override
{
100 ExtensionApiTest::SetUpCommandLine(command_line
);
101 command_line
->AppendSwitchASCII(
102 extensions::switches::kWhitelistedExtensionID
,
106 void SetUpMockCastSocket() {
107 extensions::CastChannelAPI
* api
= GetApi();
108 net::IPAddressNumber ip_number
;
109 net::ParseIPLiteralToNumber("192.168.1.1", &ip_number
);
110 net::IPEndPoint
ip_endpoint(ip_number
, 8009);
111 mock_cast_socket_
= new MockCastSocket(
112 api
, ip_endpoint
, &capturing_net_log_
, api
->GetLogger());
113 // Transfers ownership of the socket.
114 api
->SetSocketForTest(
115 make_scoped_ptr
<CastSocket
>(mock_cast_socket_
).Pass());
118 void SetUpOpenSendClose() {
119 SetUpMockCastSocket();
120 EXPECT_CALL(*mock_cast_socket_
, error_state())
121 .WillRepeatedly(Return(cast_channel::CHANNEL_ERROR_NONE
));
124 EXPECT_CALL(*mock_cast_socket_
, Connect(_
))
125 .WillOnce(InvokeCompletionCallback
<0>(net::OK
));
126 EXPECT_CALL(*mock_cast_socket_
, ready_state())
127 .WillOnce(Return(cast_channel::READY_STATE_OPEN
));
128 EXPECT_CALL(*mock_cast_socket_
, SendMessage(A
<const MessageInfo
&>(), _
))
129 .WillOnce(InvokeCompletionCallback
<1>(net::OK
));
130 EXPECT_CALL(*mock_cast_socket_
, ready_state())
131 .WillOnce(Return(cast_channel::READY_STATE_OPEN
));
132 EXPECT_CALL(*mock_cast_socket_
, Close(_
))
133 .WillOnce(InvokeCompletionCallback
<0>(net::OK
));
134 EXPECT_CALL(*mock_cast_socket_
, ready_state())
135 .WillOnce(Return(cast_channel::READY_STATE_CLOSED
));
139 extensions::CastChannelAPI
* GetApi() {
140 return extensions::CastChannelAPI::Get(profile());
143 void CallOnError(extensions::CastChannelAPI
* api
) {
144 cast_channel::LastErrors last_errors
;
145 last_errors
.challenge_reply_error_type
=
146 cast_channel::proto::CHALLENGE_REPLY_ERROR_NSS_CERT_PARSING_FAILED
;
147 last_errors
.nss_error_code
= -8164;
148 api
->OnError(mock_cast_socket_
,
149 cast_channel::CHANNEL_ERROR_CONNECT_ERROR
,
154 void CallOnMessage(const std::string
& message
) {
155 content::BrowserThread::PostTask(
156 content::BrowserThread::IO
,
158 base::Bind(&CastChannelAPITest::DoCallOnMessage
, this,
159 GetApi(), mock_cast_socket_
, message
));
162 void DoCallOnMessage(extensions::CastChannelAPI
* api
,
163 MockCastSocket
* cast_socket
,
164 const std::string
& message
) {
165 MessageInfo message_info
;
166 FillMessageInfo(&message_info
, message
);
167 api
->OnMessage(cast_socket
, message_info
);
170 extensions::CastChannelOpenFunction
* CreateOpenFunction(
171 scoped_refptr
<Extension
> extension
) {
172 extensions::CastChannelOpenFunction
* cast_channel_open_function
=
173 new extensions::CastChannelOpenFunction
;
174 cast_channel_open_function
->set_extension(extension
.get());
175 return cast_channel_open_function
;
178 extensions::CastChannelSendFunction
* CreateSendFunction(
179 scoped_refptr
<Extension
> extension
) {
180 extensions::CastChannelSendFunction
* cast_channel_send_function
=
181 new extensions::CastChannelSendFunction
;
182 cast_channel_send_function
->set_extension(extension
.get());
183 return cast_channel_send_function
;
186 extensions::CastChannelSetAuthorityKeysFunction
*
187 CreateSetAuthorityKeysFunction(scoped_refptr
<Extension
> extension
) {
188 extensions::CastChannelSetAuthorityKeysFunction
*
189 cast_channel_set_authority_keys_function
=
190 new extensions::CastChannelSetAuthorityKeysFunction
;
191 cast_channel_set_authority_keys_function
->set_extension(extension
.get());
192 return cast_channel_set_authority_keys_function
;
195 MockCastSocket
* mock_cast_socket_
;
196 net::CapturingNetLog capturing_net_log_
;
199 // TODO(munjal): Win Dbg has a workaround that makes RunExtensionSubtest
200 // always return true without actually running the test. Remove when fixed.
201 #if defined(OS_WIN) && !defined(NDEBUG)
202 #define MAYBE_TestOpenSendClose DISABLED_TestOpenSendClose
204 #define MAYBE_TestOpenSendClose TestOpenSendClose
206 // Test loading extension, opening a channel with ConnectInfo, adding a
207 // listener, writing, reading, and closing.
208 IN_PROC_BROWSER_TEST_F(CastChannelAPITest
, MAYBE_TestOpenSendClose
) {
209 SetUpOpenSendClose();
211 EXPECT_TRUE(RunExtensionSubtest("cast_channel/api",
212 "test_open_send_close.html"));
215 // TODO(munjal): Win Dbg has a workaround that makes RunExtensionSubtest
216 // always return true without actually running the test. Remove when fixed.
217 #if defined(OS_WIN) && !defined(NDEBUG)
218 #define MAYBE_TestOpenSendCloseWithUrl DISABLED_TestOpenSendCloseWithUrl
220 #define MAYBE_TestOpenSendCloseWithUrl TestOpenSendCloseWithUrl
222 // Test loading extension, opening a channel with a URL, adding a listener,
223 // writing, reading, and closing.
224 IN_PROC_BROWSER_TEST_F(CastChannelAPITest
, MAYBE_TestOpenSendCloseWithUrl
) {
225 SetUpOpenSendClose();
227 EXPECT_TRUE(RunExtensionSubtest("cast_channel/api",
228 "test_open_send_close_url.html"));
231 // TODO(munjal): Win Dbg has a workaround that makes RunExtensionSubtest
232 // always return true without actually running the test. Remove when fixed.
233 #if defined(OS_WIN) && !defined(NDEBUG)
234 #define MAYBE_TestOpenReceiveClose DISABLED_TestOpenReceiveClose
236 #define MAYBE_TestOpenReceiveClose TestOpenReceiveClose
238 // Test loading extension, opening a channel, adding a listener,
239 // writing, reading, and closing.
240 IN_PROC_BROWSER_TEST_F(CastChannelAPITest
, MAYBE_TestOpenReceiveClose
) {
241 SetUpMockCastSocket();
242 EXPECT_CALL(*mock_cast_socket_
, error_state())
243 .WillRepeatedly(Return(cast_channel::CHANNEL_ERROR_NONE
));
247 EXPECT_CALL(*mock_cast_socket_
, Connect(_
))
248 .WillOnce(InvokeCompletionCallback
<0>(net::OK
));
249 EXPECT_CALL(*mock_cast_socket_
, ready_state())
251 .WillRepeatedly(Return(cast_channel::READY_STATE_OPEN
));
252 EXPECT_CALL(*mock_cast_socket_
, Close(_
))
253 .WillOnce(InvokeCompletionCallback
<0>(net::OK
));
254 EXPECT_CALL(*mock_cast_socket_
, ready_state())
255 .WillOnce(Return(cast_channel::READY_STATE_CLOSED
));
258 EXPECT_TRUE(RunExtensionSubtest("cast_channel/api",
259 "test_open_receive_close.html"));
261 extensions::ResultCatcher catcher
;
262 CallOnMessage("some-message");
263 CallOnMessage("some-message");
264 EXPECT_TRUE(catcher
.GetNextResult()) << catcher
.message();
267 // TODO(imcheng): Win Dbg has a workaround that makes RunExtensionSubtest
268 // always return true without actually running the test. Remove when fixed.
269 #if defined(OS_WIN) && !defined(NDEBUG)
270 #define MAYBE_TestGetLogs DISABLED_TestGetLogs
272 #define MAYBE_TestGetLogs TestGetLogs
274 // Test loading extension, execute a open-send-close sequence, then get logs.
275 IN_PROC_BROWSER_TEST_F(CastChannelAPITest
, MAYBE_TestGetLogs
) {
276 SetUpOpenSendClose();
278 EXPECT_TRUE(RunExtensionSubtest("cast_channel/api", "test_get_logs.html"));
281 // TODO(munjal): Win Dbg has a workaround that makes RunExtensionSubtest
282 // always return true without actually running the test. Remove when fixed.
283 #if defined(OS_WIN) && !defined(NDEBUG)
284 #define MAYBE_TestOpenError DISABLED_TestOpenError
286 #define MAYBE_TestOpenError TestOpenError
288 // Test the case when socket open results in an error.
289 IN_PROC_BROWSER_TEST_F(CastChannelAPITest
, MAYBE_TestOpenError
) {
290 SetUpMockCastSocket();
292 EXPECT_CALL(*mock_cast_socket_
, Connect(_
))
293 .WillOnce(DoAll(InvokeDelegateOnError(this, GetApi()),
294 InvokeCompletionCallback
<0>(net::ERR_CONNECTION_FAILED
)));
295 EXPECT_CALL(*mock_cast_socket_
, error_state())
296 .WillRepeatedly(Return(cast_channel::CHANNEL_ERROR_CONNECT_ERROR
));
297 EXPECT_CALL(*mock_cast_socket_
, ready_state())
298 .WillRepeatedly(Return(cast_channel::READY_STATE_CLOSED
));
299 EXPECT_CALL(*mock_cast_socket_
, Close(_
))
300 .WillOnce(InvokeCompletionCallback
<0>(net::OK
));
302 EXPECT_TRUE(RunExtensionSubtest("cast_channel/api",
303 "test_open_error.html"));
306 IN_PROC_BROWSER_TEST_F(CastChannelAPITest
, TestOpenInvalidConnectInfo
) {
307 scoped_refptr
<Extension
> empty_extension
=
308 extensions::test_util::CreateEmptyExtension();
309 scoped_refptr
<extensions::CastChannelOpenFunction
> cast_channel_open_function
;
312 // TODO(mfoltz): Remove this test case when fixing crbug.com/331905
313 cast_channel_open_function
= CreateOpenFunction(empty_extension
);
314 std::string
error(utils::RunFunctionAndReturnError(
315 cast_channel_open_function
.get(), "[\"blargh\"]", browser()));
316 EXPECT_EQ(error
, "Invalid connect_info (invalid Cast URL blargh)");
319 // TODO(mfoltz): Remove this test case when fixing crbug.com/331905
320 cast_channel_open_function
= CreateOpenFunction(empty_extension
);
321 error
= utils::RunFunctionAndReturnError(
322 cast_channel_open_function
.get(),
324 EXPECT_EQ(error
, "Invalid connect_info (unknown type)");
326 // Invalid IP address
327 cast_channel_open_function
= CreateOpenFunction(empty_extension
);
328 error
= utils::RunFunctionAndReturnError(
329 cast_channel_open_function
.get(),
330 "[{\"ipAddress\": \"invalid_ip\", \"port\": 8009, \"auth\": \"ssl\"}]",
332 EXPECT_EQ(error
, "Invalid connect_info (invalid IP address)");
335 cast_channel_open_function
= CreateOpenFunction(empty_extension
);
336 error
= utils::RunFunctionAndReturnError(
337 cast_channel_open_function
.get(),
338 "[{\"ipAddress\": \"127.0.0.1\", \"port\": -200, \"auth\": \"ssl\"}]",
340 EXPECT_EQ(error
, "Invalid connect_info (invalid port)");
343 cast_channel_open_function
= CreateOpenFunction(empty_extension
);
344 error
= utils::RunFunctionAndReturnError(
345 cast_channel_open_function
.get(),
346 "[{\"ipAddress\": \"127.0.0.1\", \"port\": 8009}]",
348 EXPECT_EQ(error
, "connect_info.auth is required");
351 IN_PROC_BROWSER_TEST_F(CastChannelAPITest
, TestSendInvalidMessageInfo
) {
352 scoped_refptr
<Extension
> empty_extension(
353 extensions::test_util::CreateEmptyExtension());
354 scoped_refptr
<extensions::CastChannelSendFunction
> cast_channel_send_function
;
356 // Numbers are not supported
357 cast_channel_send_function
= CreateSendFunction(empty_extension
);
358 std::string
error(utils::RunFunctionAndReturnError(
359 cast_channel_send_function
.get(),
360 "[{\"channelId\": 1, \"url\": \"cast://127.0.0.1:8009\", "
362 "{\"ipAddress\": \"127.0.0.1\", \"port\": 8009, "
363 "\"auth\": \"ssl\"}, \"readyState\": \"open\"}, "
364 "{\"namespace_\": \"foo\", \"sourceId\": \"src\", "
365 "\"destinationId\": \"dest\", \"data\": 1235}]",
367 EXPECT_EQ(error
, "Invalid type of message_info.data");
369 // Missing namespace_
370 cast_channel_send_function
= CreateSendFunction(empty_extension
);
371 error
= utils::RunFunctionAndReturnError(
372 cast_channel_send_function
.get(),
373 "[{\"channelId\": 1, \"url\": \"cast://127.0.0.1:8009\", "
375 "{\"ipAddress\": \"127.0.0.1\", \"port\": 8009, "
376 "\"auth\": \"ssl\"}, \"readyState\": \"open\"}, "
377 "{\"namespace_\": \"\", \"sourceId\": \"src\", "
378 "\"destinationId\": \"dest\", \"data\": \"data\"}]",
380 EXPECT_EQ(error
, "message_info.namespace_ is required");
383 cast_channel_send_function
= CreateSendFunction(empty_extension
);
384 error
= utils::RunFunctionAndReturnError(
385 cast_channel_send_function
.get(),
386 "[{\"channelId\": 1, \"url\": \"cast://127.0.0.1:8009\", "
388 "{\"ipAddress\": \"127.0.0.1\", \"port\": 8009, "
389 "\"auth\": \"ssl\"}, \"readyState\": \"open\"}, "
390 "{\"namespace_\": \"foo\", \"sourceId\": \"\", "
391 "\"destinationId\": \"dest\", \"data\": \"data\"}]",
393 EXPECT_EQ(error
, "message_info.source_id is required");
395 // Missing destination_id
396 cast_channel_send_function
= CreateSendFunction(empty_extension
);
397 error
= utils::RunFunctionAndReturnError(
398 cast_channel_send_function
.get(),
399 "[{\"channelId\": 1, \"url\": \"cast://127.0.0.1:8009\", "
401 "{\"ipAddress\": \"127.0.0.1\", \"port\": 8009, "
402 "\"auth\": \"ssl\"}, \"readyState\": \"open\"}, "
403 "{\"namespace_\": \"foo\", \"sourceId\": \"src\", "
404 "\"destinationId\": \"\", \"data\": \"data\"}]",
406 EXPECT_EQ(error
, "message_info.destination_id is required");
409 IN_PROC_BROWSER_TEST_F(CastChannelAPITest
, TestSetAuthorityKeysInvalid
) {
410 scoped_refptr
<Extension
> empty_extension(
411 extensions::test_util::CreateEmptyExtension());
412 scoped_refptr
<extensions::CastChannelSetAuthorityKeysFunction
>
413 cast_channel_set_authority_keys_function
;
414 std::string errorResult
= "Unable to set authority keys.";
416 cast_channel_set_authority_keys_function
=
417 CreateSetAuthorityKeysFunction(empty_extension
);
418 std::string error
= utils::RunFunctionAndReturnError(
419 cast_channel_set_authority_keys_function
.get(),
420 "[\"\", \"signature\"]",
422 EXPECT_EQ(error
, errorResult
);
424 cast_channel_set_authority_keys_function
=
425 CreateSetAuthorityKeysFunction(empty_extension
);
426 error
= utils::RunFunctionAndReturnError(
427 cast_channel_set_authority_keys_function
.get(),
430 EXPECT_EQ(error
, errorResult
);
433 "CrMCCiBSnZzWf+XraY5w3SbX2PEmWfHm5SNIv2pc9xbhP0EOcxKOAjCCAQoCggEBALwigL"
434 "2A9johADuudl41fz3DZFxVlIY0LwWHKM33aYwXs1CnuIL638dDLdZ+q6BvtxNygKRHFcEg"
435 "mVDN7BRiCVukmM3SQbY2Tv/oLjIwSoGoQqNsmzNuyrL1U2bgJ1OGGoUepzk/SneO+1RmZv"
436 "tYVMBeOcf1UAYL4IrUzuFqVR+LFwDmaaMn5gglaTwSnY0FLNYuojHetFJQ1iBJ3nGg+a0g"
437 "QBLx3SXr1ea4NvTWj3/KQ9zXEFvmP1GKhbPz//YDLcsjT5ytGOeTBYysUpr3TOmZer5ufk"
438 "0K48YcqZP6OqWRXRy9ZuvMYNyGdMrP+JIcmH1X+mFHnquAt+RIgCqSxRsCAwEAAQ==";
439 std::string signature
=
440 "chCUHZKkykcwU8HzU+hm027fUTBL0dqPMtrzppwExQwK9+"
441 "XlmCjJswfce2sUUfhR1OL1tyW4hWFwu4JnuQCJ+CvmSmAh2bzRpnuSKzBfgvIDjNOAGUs7"
442 "ADaNSSWPLxp+6ko++2Dn4S9HpOt8N1v6gMWqj3Ru5IqFSQPZSvGH2ois6uE50CFayPcjQE"
443 "OVZt41noQdFd15RmKTvocoCC5tHNlaikeQ52yi0IScOlad1B1lMhoplW3rWophQaqxMumr"
444 "OcHIZ+Y+p858x5f8Pny/kuqUClmFh9B/vF07NsUHwoSL9tA5t5jCY3L5iUc/v7o3oFcW/T"
445 "gojKkX2Kg7KQ86QA==";
447 cast_channel_set_authority_keys_function
=
448 CreateSetAuthorityKeysFunction(empty_extension
);
449 error
= utils::RunFunctionAndReturnError(
450 cast_channel_set_authority_keys_function
.get(),
451 "[\"" + keys
+ "\", \"signature\"]",
453 EXPECT_EQ(error
, errorResult
);
455 cast_channel_set_authority_keys_function
=
456 CreateSetAuthorityKeysFunction(empty_extension
);
457 error
= utils::RunFunctionAndReturnError(
458 cast_channel_set_authority_keys_function
.get(),
459 "[\"keys\", \"" + signature
+ "\"]",
461 EXPECT_EQ(error
, errorResult
);
463 cast_channel_set_authority_keys_function
=
464 CreateSetAuthorityKeysFunction(empty_extension
);
465 error
= utils::RunFunctionAndReturnError(
466 cast_channel_set_authority_keys_function
.get(),
467 "[\"" + keys
+ "\", \"" + signature
+ "\"]",
469 EXPECT_EQ(error
, errorResult
);
472 IN_PROC_BROWSER_TEST_F(CastChannelAPITest
, TestSetAuthorityKeysValid
) {
473 scoped_refptr
<Extension
> empty_extension(
474 extensions::test_util::CreateEmptyExtension());
475 scoped_refptr
<extensions::CastChannelSetAuthorityKeysFunction
>
476 cast_channel_set_authority_keys_function
;
478 cast_channel_set_authority_keys_function
=
479 CreateSetAuthorityKeysFunction(empty_extension
);
481 "CrMCCiBSnZzWf+XraY5w3SbX2PEmWfHm5SNIv2pc9xbhP0EOcxKOAjCCAQoCggEBALwigL"
482 "2A9johADuudl41fz3DZFxVlIY0LwWHKM33aYwXs1CnuIL638dDLdZ+q6BvtxNygKRHFcEg"
483 "mVDN7BRiCVukmM3SQbY2Tv/oLjIwSoGoQqNsmzNuyrL1U2bgJ1OGGoUepzk/SneO+1RmZv"
484 "tYVMBeOcf1UAYL4IrUzuFqVR+LFwDmaaMn5gglaTwSnY0FLNYuojHetFJQ1iBJ3nGg+a0g"
485 "QBLx3SXr1ea4NvTWj3/KQ9zXEFvmP1GKhbPz//YDLcsjT5ytGOeTBYysUpr3TOmZer5ufk"
486 "0K48YcqZP6OqWRXRy9ZuvMYNyGdMrP+JIcmH1X+mFHnquAt+RIgCqSxRsCAwEAAQqzAgog"
487 "okjC6FTmVqVt6CMfHuF1b9vkB/n+1GUNYMxay2URxyASjgIwggEKAoIBAQCwDl4HOt+kX2"
488 "j3Icdk27Z27+6Lk/j2G4jhk7cX8BUeflJVdzwCjXtKbNO91sGccsizFc8RwfVGxNUgR/sw"
489 "9ORhDGjwXqs3jpvhvIHDcIp41oM0MpwZYuvknO3jZGxBHZzSi0hMI5CVs+dS6gVXzGCzuh"
490 "TkugA55EZVdM5ajnpnI9poCvrEhB60xaGianMfbsguL5qeqLEO/Yemj009SwXVNVp0TbyO"
491 "gkSW9LWVYE6l3yc9QVwHo7Q1WrOe8gUkys0xWg0mTNTT/VDhNOlMgVgwssd63YGJptQ6OI"
492 "QDtzSedz//eAdbmcGyHzVWbjo8DCXhV/aKfknAzIMRNeeRbS5lAgMBAAE=";
493 std::string signature
=
494 "o83oku3jP+xjTysNBalqp/ZfJRPLt8R+IUhZMepbARFSRVizLoeFW5XyUwe6lQaC+PFFQH"
495 "SZeGZyeeGRpwCJ/lef0xh6SWJlVMWNTk5+z0U84GQdizJP/CTCeHpIwMobN+kyDajgOyfD"
496 "DLhktc6LHmSlFGG6J7B8W67oziS8ZFEdrcT9WSXFrjLVyURHjvidZD5iFtuImI6k9R9OoX"
497 "LR6SyAwpjdrL+vlHMk3Gol6KQ98YpF0ghHnN3/FFW4ibvIwjmRbp+tUV3h8TRcCOjlXVGp"
498 "bzPtNRRlTqfv7Rxm5YXkZMLmJJMZiTs5+o8FMRMTQZT4hRR3DQ+A/jofViyTGA==";
500 std::string args
= "[\"" + keys
+ "\", \"" + signature
+ "\"]";
501 std::string error
= utils::RunFunctionAndReturnError(
502 cast_channel_set_authority_keys_function
.get(), args
, browser());
503 EXPECT_EQ(error
, std::string());