blob: 9848ab3f808454194c7f3c1e92b81df24be6c894 [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/sms/sms_fetcher_impl.h"
#include "base/memory/ptr_util.h"
#include "base/test/mock_callback.h"
#include "content/browser/sms/test/mock_sms_provider.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_client.h"
#include "content/public/test/test_renderer_host.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
#include "url/origin.h"
using ::testing::_;
using ::testing::Invoke;
using ::testing::NiceMock;
using ::testing::StrictMock;
namespace content {
using UserConsent = SmsFetcher::UserConsent;
using FailureType = SmsFetchFailureType;
namespace {
class MockContentBrowserClient : public ContentBrowserClient {
public:
MockContentBrowserClient() = default;
~MockContentBrowserClient() override = default;
MOCK_METHOD3(
FetchRemoteSms,
base::OnceClosure(WebContents*,
const url::Origin&,
base::OnceCallback<void(base::Optional<OriginList>,
base::Optional<std::string>,
base::Optional<FailureType>)>));
private:
DISALLOW_COPY_AND_ASSIGN(MockContentBrowserClient);
};
class MockSubscriber : public SmsFetcher::Subscriber {
public:
MockSubscriber() = default;
~MockSubscriber() override = default;
MOCK_METHOD3(OnReceive,
void(const OriginList&,
const std::string& one_time_code,
UserConsent));
MOCK_METHOD1(OnFailure, void(FailureType failure_type));
private:
DISALLOW_COPY_AND_ASSIGN(MockSubscriber);
};
class SmsFetcherImplTest : public RenderViewHostTestHarness {
public:
SmsFetcherImplTest() = default;
~SmsFetcherImplTest() override = default;
void SetUp() override {
RenderViewHostTestHarness::SetUp();
original_client_ = SetBrowserClientForTesting(&client_);
}
void TearDown() override {
if (original_client_)
SetBrowserClientForTesting(original_client_);
RenderViewHostTestHarness::TearDown();
}
protected:
MockContentBrowserClient* client() { return &client_; }
MockSmsProvider* provider() { return &provider_; }
private:
ContentBrowserClient* original_client_ = nullptr;
NiceMock<MockContentBrowserClient> client_;
NiceMock<MockSmsProvider> provider_;
DISALLOW_COPY_AND_ASSIGN(SmsFetcherImplTest);
};
} // namespace
TEST_F(SmsFetcherImplTest, ReceiveFromLocalSmsProvider) {
const url::Origin kOrigin = url::Origin::Create(GURL("https://a.com"));
StrictMock<MockSubscriber> subscriber;
SmsFetcherImpl fetcher(provider());
EXPECT_CALL(*provider(), Retrieve(_, _)).WillOnce(Invoke([&]() {
provider()->NotifyReceive(OriginList{kOrigin}, "123",
UserConsent::kObtained);
}));
EXPECT_CALL(subscriber, OnReceive(_, "123", UserConsent::kObtained));
fetcher.Subscribe(OriginList{kOrigin}, &subscriber, main_rfh());
}
TEST_F(SmsFetcherImplTest, ReceiveFromRemoteProvider) {
StrictMock<MockSubscriber> subscriber;
SmsFetcherImpl fetcher(provider());
EXPECT_CALL(*client(), FetchRemoteSms(_, _, _))
.WillOnce(Invoke(
[&](WebContents*, const url::Origin&,
base::OnceCallback<void(base::Optional<OriginList>,
base::Optional<std::string>,
base::Optional<FailureType>)> callback) {
std::move(callback).Run(
OriginList{url::Origin::Create(GURL("https://a.com"))}, "123",
base::nullopt);
return base::NullCallback();
}));
EXPECT_CALL(subscriber, OnReceive(_, "123", _));
fetcher.Subscribe(OriginList{url::Origin::Create(GURL("https://a.com"))},
&subscriber, main_rfh());
}
TEST_F(SmsFetcherImplTest, RemoteProviderTimesOut) {
StrictMock<MockSubscriber> subscriber;
SmsFetcherImpl fetcher(provider());
EXPECT_CALL(*client(), FetchRemoteSms(_, _, _))
.WillOnce(Invoke(
[&](WebContents*, const url::Origin&,
base::OnceCallback<void(base::Optional<OriginList>,
base::Optional<std::string>,
base::Optional<FailureType>)> callback) {
std::move(callback).Run(base::nullopt, base::nullopt,
base::nullopt);
return base::NullCallback();
}));
EXPECT_CALL(subscriber, OnReceive(_, _, _)).Times(0);
fetcher.Subscribe(OriginList{url::Origin::Create(GURL("https://a.com"))},
&subscriber, main_rfh());
}
TEST_F(SmsFetcherImplTest, ReceiveFromOtherOrigin) {
StrictMock<MockSubscriber> subscriber;
SmsFetcherImpl fetcher(provider());
EXPECT_CALL(*client(), FetchRemoteSms(_, _, _))
.WillOnce(Invoke(
[&](WebContents*, const url::Origin&,
base::OnceCallback<void(base::Optional<OriginList>,
base::Optional<std::string>,
base::Optional<FailureType>)> callback) {
std::move(callback).Run(
OriginList{url::Origin::Create(GURL("b.com"))}, "123",
base::nullopt);
return base::NullCallback();
}));
EXPECT_CALL(subscriber, OnReceive(_, _, _)).Times(0);
fetcher.Subscribe(OriginList{url::Origin::Create(GURL("https://a.com"))},
&subscriber, main_rfh());
}
TEST_F(SmsFetcherImplTest, ReceiveFromBothProviders) {
const url::Origin kOrigin = url::Origin::Create(GURL("https://a.com"));
StrictMock<MockSubscriber> subscriber;
SmsFetcherImpl fetcher(provider());
const std::string& sms = "hello\n@a.com #123";
EXPECT_CALL(*client(), FetchRemoteSms(_, _, _))
.WillOnce(Invoke(
[&](WebContents*, const url::Origin&,
base::OnceCallback<void(base::Optional<OriginList>,
base::Optional<std::string>,
base::Optional<FailureType>)> callback) {
std::move(callback).Run(
OriginList{url::Origin::Create(GURL("https://a.com"))}, "123",
base::nullopt);
return base::NullCallback();
}));
EXPECT_CALL(*provider(), Retrieve(_, _)).WillOnce(Invoke([&]() {
provider()->NotifyReceive(OriginList{kOrigin}, sms,
UserConsent::kNotObtained);
}));
// Expects subscriber to be notified just once.
EXPECT_CALL(subscriber, OnReceive(_, "123", UserConsent::kObtained));
fetcher.Subscribe(OriginList{kOrigin}, &subscriber, main_rfh());
}
TEST_F(SmsFetcherImplTest, OneOriginTwoSubscribers) {
const url::Origin kOrigin = url::Origin::Create(GURL("https://a.com"));
StrictMock<MockSubscriber> subscriber1;
StrictMock<MockSubscriber> subscriber2;
SmsFetcherImpl fetcher(provider());
fetcher.Subscribe(OriginList{kOrigin}, &subscriber1, main_rfh());
fetcher.Subscribe(OriginList{kOrigin}, &subscriber2, main_rfh());
EXPECT_CALL(subscriber1, OnReceive(_, "123", UserConsent::kObtained));
provider()->NotifyReceive(OriginList{kOrigin}, "123", UserConsent::kObtained);
EXPECT_CALL(subscriber2, OnReceive(_, "456", UserConsent::kObtained));
provider()->NotifyReceive(OriginList{kOrigin}, "456", UserConsent::kObtained);
}
TEST_F(SmsFetcherImplTest, TwoOriginsTwoSubscribers) {
const url::Origin kOrigin1 = url::Origin::Create(GURL("https://a.com"));
const url::Origin kOrigin2 = url::Origin::Create(GURL("https://b.com"));
StrictMock<MockSubscriber> subscriber1;
StrictMock<MockSubscriber> subscriber2;
SmsFetcherImpl fetcher(provider());
fetcher.Subscribe(OriginList{kOrigin1}, &subscriber1, main_rfh());
fetcher.Subscribe(OriginList{kOrigin2}, &subscriber2, main_rfh());
EXPECT_CALL(subscriber2, OnReceive(_, "456", UserConsent::kObtained));
provider()->NotifyReceive(OriginList{kOrigin2}, "456",
UserConsent::kObtained);
EXPECT_CALL(subscriber1, OnReceive(_, "123", UserConsent::kObtained));
provider()->NotifyReceive(OriginList{kOrigin1}, "123",
UserConsent::kObtained);
}
TEST_F(SmsFetcherImplTest, OneOriginTwoSubscribersOnlyOneIsNotifiedFailed) {
const url::Origin kOrigin = url::Origin::Create(GURL("https://a.com"));
StrictMock<MockSubscriber> subscriber1;
StrictMock<MockSubscriber> subscriber2;
SmsFetcherImpl fetcher1(provider());
SmsFetcherImpl fetcher2(provider());
fetcher1.Subscribe(OriginList{kOrigin}, &subscriber1, main_rfh());
fetcher2.Subscribe(OriginList{kOrigin}, &subscriber2, main_rfh());
EXPECT_CALL(subscriber1, OnFailure(FailureType::kPromptTimeout));
EXPECT_CALL(subscriber2, OnFailure(FailureType::kPromptTimeout)).Times(0);
provider()->NotifyFailure(FailureType::kPromptTimeout);
}
TEST_F(SmsFetcherImplTest, FetchRemoteSmsFailed) {
StrictMock<MockSubscriber> subscriber;
SmsFetcherImpl fetcher(provider());
EXPECT_CALL(*client(), FetchRemoteSms(_, _, _))
.WillOnce(Invoke(
[&](WebContents*, const url::Origin&,
base::OnceCallback<void(base::Optional<OriginList>,
base::Optional<std::string>,
base::Optional<FailureType>)> callback) {
std::move(callback).Run(
base::nullopt, base::nullopt,
static_cast<FailureType>(FailureType::kPromptCancelled));
return base::NullCallback();
}));
EXPECT_CALL(subscriber, OnFailure(_));
fetcher.Subscribe(OriginList{url::Origin::Create(GURL("https://a.com"))},
&subscriber, main_rfh());
}
TEST_F(SmsFetcherImplTest, FetchRemoteSmsCancelled) {
StrictMock<MockSubscriber> subscriber;
SmsFetcherImpl fetcher(provider());
base::MockOnceClosure cancel_callback;
EXPECT_CALL(*client(), FetchRemoteSms(_, _, _))
.WillOnce(Invoke(
[&](WebContents*, const url::Origin&,
base::OnceCallback<void(base::Optional<OriginList>,
base::Optional<std::string>,
base::Optional<FailureType>)> callback) {
return cancel_callback.Get();
}));
EXPECT_CALL(cancel_callback, Run).Times(0);
OriginList origin_list =
OriginList{url::Origin::Create(GURL("https://a.com"))};
fetcher.Subscribe(origin_list, &subscriber, main_rfh());
testing::Mock::VerifyAndClearExpectations(&cancel_callback);
EXPECT_CALL(cancel_callback, Run);
fetcher.Unsubscribe(origin_list, &subscriber);
}
} // namespace content