| Index: chrome/browser/media/router/mojo/media_router_mojo_impl_unittest.cc
|
| diff --git a/chrome/browser/media/router/mojo/media_router_mojo_impl_unittest.cc b/chrome/browser/media/router/mojo/media_router_mojo_impl_unittest.cc
|
| index 70df1a64efa7b541408d70df3a06784c8b6f12c2..e36055277921e7499c1e5a35718c4be4bd4c7531 100644
|
| --- a/chrome/browser/media/router/mojo/media_router_mojo_impl_unittest.cc
|
| +++ b/chrome/browser/media/router/mojo/media_router_mojo_impl_unittest.cc
|
| @@ -195,11 +195,10 @@
|
| // a limitation with GMock::Invoke that prevents it from using move-only types
|
| // in runnable parameter lists.
|
| EXPECT_CALL(mock_media_route_provider_,
|
| - CreateRoute(kSource, kSinkId, _, url::Origin(GURL(kOrigin)),
|
| - kInvalidTabId, _, _, _))
|
| + CreateRoute(kSource, kSinkId, _, kOrigin, kInvalidTabId, _, _, _))
|
| .WillOnce(Invoke(
|
| [](const std::string& source, const std::string& sink,
|
| - const std::string& presentation_id, const url::Origin& origin,
|
| + const std::string& presentation_id, const std::string& origin,
|
| int tab_id, base::TimeDelta timeout, bool incognito,
|
| const mojom::MediaRouteProvider::CreateRouteCallback& cb) {
|
| cb.Run(CreateMojoRoute(), std::string(),
|
| @@ -214,10 +213,9 @@
|
| std::vector<MediaRouteResponseCallback> route_response_callbacks;
|
| route_response_callbacks.push_back(base::Bind(
|
| &RouteResponseCallbackHandler::Invoke, base::Unretained(&handler)));
|
| - router()->CreateRoute(kSource, kSinkId, url::Origin(GURL(kOrigin)), nullptr,
|
| - route_response_callbacks,
|
| - base::TimeDelta::FromMilliseconds(kTimeoutMillis),
|
| - false);
|
| + router()->CreateRoute(
|
| + kSource, kSinkId, GURL(kOrigin), nullptr, route_response_callbacks,
|
| + base::TimeDelta::FromMilliseconds(kTimeoutMillis), false);
|
| run_loop.Run();
|
| ExpectResultBucketCount("CreateRoute", RouteRequestResult::ResultCode::OK, 1);
|
| }
|
| @@ -232,11 +230,10 @@
|
| // a limitation with GMock::Invoke that prevents it from using move-only types
|
| // in runnable parameter lists.
|
| EXPECT_CALL(mock_media_route_provider_,
|
| - CreateRoute(kSource, kSinkId, _, url::Origin(GURL(kOrigin)),
|
| - kInvalidTabId, _, _, _))
|
| + CreateRoute(kSource, kSinkId, _, kOrigin, kInvalidTabId, _, _, _))
|
| .WillOnce(Invoke(
|
| [](const std::string& source, const std::string& sink,
|
| - const std::string& presentation_id, const url::Origin& origin,
|
| + const std::string& presentation_id, const std::string& origin,
|
| int tab_id, base::TimeDelta timeout, bool incognito,
|
| const mojom::MediaRouteProvider::CreateRouteCallback& cb) {
|
| mojom::MediaRoutePtr route = CreateMojoRoute();
|
| @@ -255,10 +252,9 @@
|
| std::vector<MediaRouteResponseCallback> route_response_callbacks;
|
| route_response_callbacks.push_back(base::Bind(
|
| &RouteResponseCallbackHandler::Invoke, base::Unretained(&handler)));
|
| - router()->CreateRoute(kSource, kSinkId, url::Origin(GURL(kOrigin)), nullptr,
|
| - route_response_callbacks,
|
| - base::TimeDelta::FromMilliseconds(kTimeoutMillis),
|
| - true);
|
| + router()->CreateRoute(
|
| + kSource, kSinkId, GURL(kOrigin), nullptr, route_response_callbacks,
|
| + base::TimeDelta::FromMilliseconds(kTimeoutMillis), true);
|
| run_loop.Run();
|
| ExpectResultBucketCount("CreateRoute", RouteRequestResult::ResultCode::OK, 1);
|
| }
|
| @@ -266,12 +262,11 @@
|
| TEST_F(MediaRouterMojoImplTest, CreateRouteFails) {
|
| EXPECT_CALL(
|
| mock_media_route_provider_,
|
| - CreateRoute(kSource, kSinkId, _, url::Origin(GURL(kOrigin)),
|
| - kInvalidTabId,
|
| + CreateRoute(kSource, kSinkId, _, kOrigin, kInvalidTabId,
|
| base::TimeDelta::FromMilliseconds(kTimeoutMillis), _, _))
|
| .WillOnce(Invoke(
|
| [](const std::string& source, const std::string& sink,
|
| - const std::string& presentation_id, const url::Origin& origin,
|
| + const std::string& presentation_id, const std::string& origin,
|
| int tab_id, base::TimeDelta timeout, bool incognito,
|
| const mojom::MediaRouteProvider::CreateRouteCallback& cb) {
|
| cb.Run(mojom::MediaRoutePtr(), std::string(kError),
|
| @@ -286,24 +281,22 @@
|
| std::vector<MediaRouteResponseCallback> route_response_callbacks;
|
| route_response_callbacks.push_back(base::Bind(
|
| &RouteResponseCallbackHandler::Invoke, base::Unretained(&handler)));
|
| - router()->CreateRoute(kSource, kSinkId, url::Origin(GURL(kOrigin)), nullptr,
|
| - route_response_callbacks,
|
| - base::TimeDelta::FromMilliseconds(kTimeoutMillis),
|
| - false);
|
| + router()->CreateRoute(
|
| + kSource, kSinkId, GURL(kOrigin), nullptr, route_response_callbacks,
|
| + base::TimeDelta::FromMilliseconds(kTimeoutMillis), false);
|
| run_loop.Run();
|
| ExpectResultBucketCount("CreateRoute",
|
| RouteRequestResult::ResultCode::TIMED_OUT, 1);
|
| }
|
|
|
| TEST_F(MediaRouterMojoImplTest, CreateRouteIncognitoMismatchFails) {
|
| - EXPECT_CALL(
|
| - mock_media_route_provider_,
|
| - CreateRoute(kSource, kSinkId, _, url::Origin(GURL(kOrigin)),
|
| - kInvalidTabId,
|
| - base::TimeDelta::FromMilliseconds(kTimeoutMillis), true, _))
|
| + EXPECT_CALL(mock_media_route_provider_,
|
| + CreateRoute(kSource, kSinkId, _, kOrigin, kInvalidTabId,
|
| + base::TimeDelta::FromMilliseconds(kTimeoutMillis),
|
| + true, _))
|
| .WillOnce(Invoke(
|
| [](const std::string& source, const std::string& sink,
|
| - const std::string& presentation_id, const url::Origin& origin,
|
| + const std::string& presentation_id, const std::string& origin,
|
| int tab_id, base::TimeDelta timeout, bool incognito,
|
| const mojom::MediaRouteProvider::CreateRouteCallback& cb) {
|
| cb.Run(CreateMojoRoute(), std::string(),
|
| @@ -319,10 +312,9 @@
|
| std::vector<MediaRouteResponseCallback> route_response_callbacks;
|
| route_response_callbacks.push_back(base::Bind(
|
| &RouteResponseCallbackHandler::Invoke, base::Unretained(&handler)));
|
| - router()->CreateRoute(kSource, kSinkId, url::Origin(GURL(kOrigin)), nullptr,
|
| - route_response_callbacks,
|
| - base::TimeDelta::FromMilliseconds(kTimeoutMillis),
|
| - true);
|
| + router()->CreateRoute(
|
| + kSource, kSinkId, GURL(kOrigin), nullptr, route_response_callbacks,
|
| + base::TimeDelta::FromMilliseconds(kTimeoutMillis), true);
|
| run_loop.Run();
|
| ExpectResultBucketCount(
|
| "CreateRoute", RouteRequestResult::ResultCode::INCOGNITO_MISMATCH, 1);
|
| @@ -332,14 +324,13 @@
|
| mojom::MediaRoutePtr route = CreateMojoRoute();
|
| route->is_incognito = true;
|
|
|
| - EXPECT_CALL(
|
| - mock_media_route_provider_,
|
| - CreateRoute(kSource, kSinkId, _, url::Origin(GURL(kOrigin)),
|
| - kInvalidTabId,
|
| - base::TimeDelta::FromMilliseconds(kTimeoutMillis), true, _))
|
| + EXPECT_CALL(mock_media_route_provider_,
|
| + CreateRoute(kSource, kSinkId, _, kOrigin, kInvalidTabId,
|
| + base::TimeDelta::FromMilliseconds(kTimeoutMillis),
|
| + true, _))
|
| .WillOnce(Invoke(
|
| [](const std::string& source, const std::string& sink,
|
| - const std::string& presentation_id, const url::Origin& origin,
|
| + const std::string& presentation_id, const std::string& origin,
|
| int tab_id, base::TimeDelta timeout, bool incognito,
|
| const mojom::MediaRouteProvider::CreateRouteCallback& cb) {
|
| mojom::MediaRoutePtr route = CreateMojoRoute();
|
| @@ -348,7 +339,7 @@
|
| mojom::RouteRequestResultCode::OK);
|
| }));
|
| base::RunLoop run_loop;
|
| - router()->CreateRoute(kSource, kSinkId, url::Origin(GURL(kOrigin)), nullptr,
|
| + router()->CreateRoute(kSource, kSinkId, GURL(kOrigin), nullptr,
|
| std::vector<MediaRouteResponseCallback>(),
|
| base::TimeDelta::FromMilliseconds(kTimeoutMillis),
|
| true);
|
| @@ -392,12 +383,11 @@
|
| // in runnable parameter lists.
|
| EXPECT_CALL(
|
| mock_media_route_provider_,
|
| - JoinRoute(kSource, kPresentationId, url::Origin(GURL(kOrigin)),
|
| - kInvalidTabId,
|
| + JoinRoute(kSource, kPresentationId, kOrigin, kInvalidTabId,
|
| base::TimeDelta::FromMilliseconds(kTimeoutMillis), _, _))
|
| .WillOnce(Invoke([&route](
|
| const std::string& source, const std::string& presentation_id,
|
| - const url::Origin& origin, int tab_id, base::TimeDelta timeout,
|
| + const std::string& origin, int tab_id, base::TimeDelta timeout,
|
| bool incognito,
|
| const mojom::MediaRouteProvider::JoinRouteCallback& cb) {
|
| cb.Run(std::move(route), std::string(),
|
| @@ -412,8 +402,8 @@
|
| std::vector<MediaRouteResponseCallback> route_response_callbacks;
|
| route_response_callbacks.push_back(base::Bind(
|
| &RouteResponseCallbackHandler::Invoke, base::Unretained(&handler)));
|
| - router()->JoinRoute(kSource, kPresentationId, url::Origin(GURL(kOrigin)),
|
| - nullptr, route_response_callbacks,
|
| + router()->JoinRoute(kSource, kPresentationId, GURL(kOrigin), nullptr,
|
| + route_response_callbacks,
|
| base::TimeDelta::FromMilliseconds(kTimeoutMillis), false);
|
| run_loop.Run();
|
| ExpectResultBucketCount("JoinRoute", RouteRequestResult::ResultCode::OK, 1);
|
| @@ -428,8 +418,8 @@
|
| std::vector<MediaRouteResponseCallback> route_response_callbacks;
|
| route_response_callbacks.push_back(base::Bind(
|
| &RouteResponseCallbackHandler::Invoke, base::Unretained(&handler)));
|
| - router()->JoinRoute(kSource, kPresentationId, url::Origin(GURL(kOrigin)),
|
| - nullptr, route_response_callbacks,
|
| + router()->JoinRoute(kSource, kPresentationId, GURL(kOrigin), nullptr,
|
| + route_response_callbacks,
|
| base::TimeDelta::FromMilliseconds(kTimeoutMillis), false);
|
| run_loop.Run();
|
| ExpectResultBucketCount("JoinRoute",
|
| @@ -447,12 +437,11 @@
|
|
|
| EXPECT_CALL(
|
| mock_media_route_provider_,
|
| - JoinRoute(kSource, kPresentationId, url::Origin(GURL(kOrigin)),
|
| - kInvalidTabId,
|
| + JoinRoute(kSource, kPresentationId, kOrigin, kInvalidTabId,
|
| base::TimeDelta::FromMilliseconds(kTimeoutMillis), _, _))
|
| .WillOnce(Invoke(
|
| [](const std::string& source, const std::string& presentation_id,
|
| - const url::Origin& origin, int tab_id, base::TimeDelta timeout,
|
| + const std::string& origin, int tab_id, base::TimeDelta timeout,
|
| bool incognito,
|
| const mojom::MediaRouteProvider::JoinRouteCallback& cb) {
|
| cb.Run(mojom::MediaRoutePtr(), std::string(kError),
|
| @@ -467,8 +456,8 @@
|
| std::vector<MediaRouteResponseCallback> route_response_callbacks;
|
| route_response_callbacks.push_back(base::Bind(
|
| &RouteResponseCallbackHandler::Invoke, base::Unretained(&handler)));
|
| - router()->JoinRoute(kSource, kPresentationId, url::Origin(GURL(kOrigin)),
|
| - nullptr, route_response_callbacks,
|
| + router()->JoinRoute(kSource, kPresentationId, GURL(kOrigin), nullptr,
|
| + route_response_callbacks,
|
| base::TimeDelta::FromMilliseconds(kTimeoutMillis), false);
|
| run_loop.Run();
|
| ExpectResultBucketCount("JoinRoute",
|
| @@ -491,12 +480,11 @@
|
| // in runnable parameter lists.
|
| EXPECT_CALL(
|
| mock_media_route_provider_,
|
| - JoinRoute(kSource, kPresentationId, url::Origin(GURL(kOrigin)),
|
| - kInvalidTabId,
|
| + JoinRoute(kSource, kPresentationId, kOrigin, kInvalidTabId,
|
| base::TimeDelta::FromMilliseconds(kTimeoutMillis), true, _))
|
| .WillOnce(Invoke([&route](
|
| const std::string& source, const std::string& presentation_id,
|
| - const url::Origin& origin, int tab_id, base::TimeDelta timeout,
|
| + const std::string& origin, int tab_id, base::TimeDelta timeout,
|
| bool incognito,
|
| const mojom::MediaRouteProvider::JoinRouteCallback& cb) {
|
| cb.Run(std::move(route), std::string(),
|
| @@ -512,8 +500,8 @@
|
| std::vector<MediaRouteResponseCallback> route_response_callbacks;
|
| route_response_callbacks.push_back(base::Bind(
|
| &RouteResponseCallbackHandler::Invoke, base::Unretained(&handler)));
|
| - router()->JoinRoute(kSource, kPresentationId, url::Origin(GURL(kOrigin)),
|
| - nullptr, route_response_callbacks,
|
| + router()->JoinRoute(kSource, kPresentationId, GURL(kOrigin), nullptr,
|
| + route_response_callbacks,
|
| base::TimeDelta::FromMilliseconds(kTimeoutMillis), true);
|
| run_loop.Run();
|
| ExpectResultBucketCount(
|
| @@ -532,12 +520,12 @@
|
| // in runnable parameter lists.
|
| EXPECT_CALL(
|
| mock_media_route_provider_,
|
| - ConnectRouteByRouteId(
|
| - kSource, kRouteId, _, url::Origin(GURL(kOrigin)), kInvalidTabId,
|
| - base::TimeDelta::FromMilliseconds(kTimeoutMillis), false, _))
|
| + ConnectRouteByRouteId(kSource, kRouteId, _, kOrigin, kInvalidTabId,
|
| + base::TimeDelta::FromMilliseconds(kTimeoutMillis),
|
| + false, _))
|
| .WillOnce(Invoke([&route](
|
| const std::string& source, const std::string& route_id,
|
| - const std::string& presentation_id, const url::Origin& origin,
|
| + const std::string& presentation_id, const std::string& origin,
|
| int tab_id, base::TimeDelta timeout, bool incognito,
|
| const mojom::MediaRouteProvider::JoinRouteCallback& cb) {
|
| cb.Run(std::move(route), std::string(),
|
| @@ -553,8 +541,7 @@
|
| route_response_callbacks.push_back(base::Bind(
|
| &RouteResponseCallbackHandler::Invoke, base::Unretained(&handler)));
|
| router()->ConnectRouteByRouteId(
|
| - kSource, kRouteId, url::Origin(GURL(kOrigin)), nullptr,
|
| - route_response_callbacks,
|
| + kSource, kRouteId, GURL(kOrigin), nullptr, route_response_callbacks,
|
| base::TimeDelta::FromMilliseconds(kTimeoutMillis), false);
|
| run_loop.Run();
|
| ExpectResultBucketCount("JoinRoute", RouteRequestResult::ResultCode::OK, 1);
|
| @@ -563,12 +550,12 @@
|
| TEST_F(MediaRouterMojoImplTest, ConnectRouteByRouteIdFails) {
|
| EXPECT_CALL(
|
| mock_media_route_provider_,
|
| - ConnectRouteByRouteId(
|
| - kSource, kRouteId, _, url::Origin(GURL(kOrigin)), kInvalidTabId,
|
| - base::TimeDelta::FromMilliseconds(kTimeoutMillis), true, _))
|
| + ConnectRouteByRouteId(kSource, kRouteId, _, kOrigin, kInvalidTabId,
|
| + base::TimeDelta::FromMilliseconds(kTimeoutMillis),
|
| + true, _))
|
| .WillOnce(Invoke(
|
| [](const std::string& source, const std::string& route_id,
|
| - const std::string& presentation_id, const url::Origin& origin,
|
| + const std::string& presentation_id, const std::string& origin,
|
| int tab_id, base::TimeDelta timeout, bool incognito,
|
| const mojom::MediaRouteProvider::JoinRouteCallback& cb) {
|
| cb.Run(mojom::MediaRoutePtr(), std::string(kError),
|
| @@ -584,8 +571,7 @@
|
| route_response_callbacks.push_back(base::Bind(
|
| &RouteResponseCallbackHandler::Invoke, base::Unretained(&handler)));
|
| router()->ConnectRouteByRouteId(
|
| - kSource, kRouteId, url::Origin(GURL(kOrigin)), nullptr,
|
| - route_response_callbacks,
|
| + kSource, kRouteId, GURL(kOrigin), nullptr, route_response_callbacks,
|
| base::TimeDelta::FromMilliseconds(kTimeoutMillis), true);
|
| run_loop.Run();
|
| ExpectResultBucketCount("JoinRoute",
|
| @@ -600,12 +586,12 @@
|
| // in runnable parameter lists.
|
| EXPECT_CALL(
|
| mock_media_route_provider_,
|
| - ConnectRouteByRouteId(
|
| - kSource, kRouteId, _, url::Origin(GURL(kOrigin)), kInvalidTabId,
|
| - base::TimeDelta::FromMilliseconds(kTimeoutMillis), true, _))
|
| + ConnectRouteByRouteId(kSource, kRouteId, _, kOrigin, kInvalidTabId,
|
| + base::TimeDelta::FromMilliseconds(kTimeoutMillis),
|
| + true, _))
|
| .WillOnce(Invoke([&route](
|
| const std::string& source, const std::string& route_id,
|
| - const std::string& presentation_id, const url::Origin& origin,
|
| + const std::string& presentation_id, const std::string& origin,
|
| int tab_id, base::TimeDelta timeout, bool incognito,
|
| const mojom::MediaRouteProvider::JoinRouteCallback& cb) {
|
| cb.Run(std::move(route), std::string(),
|
| @@ -622,8 +608,7 @@
|
| route_response_callbacks.push_back(base::Bind(
|
| &RouteResponseCallbackHandler::Invoke, base::Unretained(&handler)));
|
| router()->ConnectRouteByRouteId(
|
| - kSource, kRouteId, url::Origin(GURL(kOrigin)), nullptr,
|
| - route_response_callbacks,
|
| + kSource, kRouteId, GURL(kOrigin), nullptr, route_response_callbacks,
|
| base::TimeDelta::FromMilliseconds(kTimeoutMillis), true);
|
| run_loop.Run();
|
| ExpectResultBucketCount(
|
| @@ -711,6 +696,7 @@
|
| router()->OnSinkAvailabilityUpdated(
|
| mojom::MediaRouter::SinkAvailability::AVAILABLE);
|
| MediaSource media_source(kSource);
|
| + GURL origin("https://google.com");
|
|
|
| // These should only be called once even if there is more than one observer
|
| // for a given source.
|
| @@ -718,16 +704,13 @@
|
| EXPECT_CALL(mock_media_route_provider_, StartObservingMediaSinks(kSource2));
|
|
|
| std::unique_ptr<MockMediaSinksObserver> sinks_observer(
|
| - new MockMediaSinksObserver(router(), media_source,
|
| - url::Origin(GURL(kOrigin))));
|
| + new MockMediaSinksObserver(router(), media_source, origin));
|
| EXPECT_TRUE(sinks_observer->Init());
|
| std::unique_ptr<MockMediaSinksObserver> extra_sinks_observer(
|
| - new MockMediaSinksObserver(router(), media_source,
|
| - url::Origin(GURL(kOrigin))));
|
| + new MockMediaSinksObserver(router(), media_source, origin));
|
| EXPECT_TRUE(extra_sinks_observer->Init());
|
| std::unique_ptr<MockMediaSinksObserver> unrelated_sinks_observer(
|
| - new MockMediaSinksObserver(router(), MediaSource(kSource2),
|
| - url::Origin(GURL(kOrigin))));
|
| + new MockMediaSinksObserver(router(), MediaSource(kSource2), origin));
|
| EXPECT_TRUE(unrelated_sinks_observer->Init());
|
| ProcessEventLoop();
|
|
|
| @@ -756,15 +739,14 @@
|
| .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); }));
|
| media_router_proxy_->OnSinksReceived(
|
| media_source.id(), std::move(mojo_sinks),
|
| - std::vector<url::Origin>(1, url::Origin(GURL(kOrigin))));
|
| + std::vector<std::string>(1, origin.spec()));
|
| run_loop.Run();
|
|
|
| // Since the MediaRouterMojoImpl has already received results for
|
| // |media_source|, return cached results to observers that are subsequently
|
| // registered.
|
| std::unique_ptr<MockMediaSinksObserver> cached_sinks_observer(
|
| - new MockMediaSinksObserver(router(), media_source,
|
| - url::Origin(GURL(kOrigin))));
|
| + new MockMediaSinksObserver(router(), media_source, origin));
|
| EXPECT_CALL(*cached_sinks_observer,
|
| OnSinksReceived(SequenceEquals(expected_sinks)));
|
| EXPECT_TRUE(cached_sinks_observer->Init());
|
| @@ -772,7 +754,7 @@
|
| // Different origin from cached result. Empty list will be returned.
|
| std::unique_ptr<MockMediaSinksObserver> cached_sinks_observer2(
|
| new MockMediaSinksObserver(router(), media_source,
|
| - url::Origin(GURL("https://youtube.com"))));
|
| + GURL("https://youtube.com")));
|
| EXPECT_CALL(*cached_sinks_observer2, OnSinksReceived(IsEmpty()));
|
| EXPECT_TRUE(cached_sinks_observer2->Init());
|
|
|
| @@ -790,20 +772,19 @@
|
|
|
| TEST_F(MediaRouterMojoImplTest,
|
| RegisterMediaSinksObserverWithAvailabilityChange) {
|
| + GURL origin("https://google.com");
|
|
|
| // When availability is UNAVAILABLE, no calls should be made to MRPM.
|
| router()->OnSinkAvailabilityUpdated(
|
| mojom::MediaRouter::SinkAvailability::UNAVAILABLE);
|
| MediaSource media_source(kSource);
|
| std::unique_ptr<MockMediaSinksObserver> sinks_observer(
|
| - new MockMediaSinksObserver(router(), media_source,
|
| - url::Origin(GURL(kOrigin))));
|
| + new MockMediaSinksObserver(router(), media_source, origin));
|
| EXPECT_CALL(*sinks_observer, OnSinksReceived(IsEmpty()));
|
| EXPECT_TRUE(sinks_observer->Init());
|
| MediaSource media_source2(kSource2);
|
| std::unique_ptr<MockMediaSinksObserver> sinks_observer2(
|
| - new MockMediaSinksObserver(router(), media_source2,
|
| - url::Origin(GURL(kOrigin))));
|
| + new MockMediaSinksObserver(router(), media_source2, origin));
|
| EXPECT_CALL(*sinks_observer2, OnSinksReceived(IsEmpty()));
|
| EXPECT_TRUE(sinks_observer2->Init());
|
| EXPECT_CALL(mock_media_route_provider_, StartObservingMediaSinks(kSource))
|
|
|