Commit dcd50fae authored by Majid Valipour's avatar Majid Valipour Committed by Commit Bot

[WebOTP] Refactor sms service tests to not require a particular backend

Currently the sms_service_unittests only exercises the verification
backend which is not actually active by default since we are
currently using User Consent backend.

More than half the tests (10 out of 10) seems to apply to both backends.
This patch refactors the logic so that the backend specific part of
sms service are well encapsulated.

It then updates the test so these common tests are exercised with
both backends.

Changes:
 - Introduce UserConsentHandler with two specific implementation
    1. Noop: which does not show any UI to user and is used with user
       consent backend.
    2. PromptBased: which prompts user to give consent and is used with
       verification backend. This encapsulates previous OpenInfoBar,
       OnCancel, OnConfirm methods from sms service.
 - The consent handler is created on construction of the service and is
   used for its lifetime. This makes it possible to easily inject mock
   consent handlers for testing.
 - Update mock Service to use a simple Noop consent handler for common
   tests which don't involve consent.
 - Introduce a more specialized ServiceWithPrompt that uses a prompt
   based consent handler for tests specific to prompt based logic.
 - Add unit tests for consent handlers.
 - Minor renaming, comments to clarify the code further.


There is not expected to be any functional changes in this CL.


Change-Id: I411bf9d12cb7a2051e545ce6dd8a50fe37204326
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2254447Reviewed-by: default avatarSam Goto <goto@chromium.org>
Commit-Queue: Majid Valipour <majidvp@chromium.org>
Cr-Commit-Position: refs/heads/master@{#789970}
parent 2a03c3dd
...@@ -1793,6 +1793,8 @@ jumbo_source_set("browser") { ...@@ -1793,6 +1793,8 @@ jumbo_source_set("browser") {
"sms/sms_queue.h", "sms/sms_queue.h",
"sms/sms_service.cc", "sms/sms_service.cc",
"sms/sms_service.h", "sms/sms_service.h",
"sms/user_consent_handler.cc",
"sms/user_consent_handler.h",
"speech/speech_recognition_dispatcher_host.cc", "speech/speech_recognition_dispatcher_host.cc",
"speech/speech_recognition_dispatcher_host.h", "speech/speech_recognition_dispatcher_host.h",
"speech/speech_recognition_manager_impl.cc", "speech/speech_recognition_manager_impl.cc",
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "content/browser/sms/sms_service.h" #include "content/browser/sms/sms_service.h"
#include <iterator> #include <iterator>
#include <memory>
#include <queue> #include <queue>
#include <string> #include <string>
#include <utility> #include <utility>
...@@ -16,6 +17,7 @@ ...@@ -16,6 +17,7 @@
#include "base/optional.h" #include "base/optional.h"
#include "content/browser/frame_host/render_frame_host_impl.h" #include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/sms/sms_metrics.h" #include "content/browser/sms/sms_metrics.h"
#include "content/browser/sms/user_consent_handler.h"
#include "content/public/browser/navigation_details.h" #include "content/public/browser/navigation_details.h"
#include "content/public/browser/navigation_type.h" #include "content/public/browser/navigation_type.h"
#include "content/public/browser/sms_fetcher.h" #include "content/public/browser/sms_fetcher.h"
...@@ -23,6 +25,7 @@ ...@@ -23,6 +25,7 @@
#include "content/public/browser/web_contents_delegate.h" #include "content/public/browser/web_contents_delegate.h"
#include "content/public/common/content_features.h" #include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h" #include "content/public/common/content_switches.h"
#include "third_party/blink/public/mojom/sms/sms_receiver.mojom-shared.h"
using blink::SmsReceiverDestroyedReason; using blink::SmsReceiverDestroyedReason;
using blink::mojom::SmsStatus; using blink::mojom::SmsStatus;
...@@ -31,11 +34,13 @@ namespace content { ...@@ -31,11 +34,13 @@ namespace content {
SmsService::SmsService( SmsService::SmsService(
SmsFetcher* fetcher, SmsFetcher* fetcher,
std::unique_ptr<UserConsentHandler> consent_handler,
const url::Origin& origin, const url::Origin& origin,
RenderFrameHost* host, RenderFrameHost* host,
mojo::PendingReceiver<blink::mojom::SmsReceiver> receiver) mojo::PendingReceiver<blink::mojom::SmsReceiver> receiver)
: FrameServiceBase(host, std::move(receiver)), : FrameServiceBase(host, std::move(receiver)),
fetcher_(fetcher), fetcher_(fetcher),
consent_handler_(std::move(consent_handler)),
origin_(origin) { origin_(origin) {
DCHECK(fetcher_); DCHECK(fetcher_);
} }
...@@ -45,13 +50,24 @@ SmsService::SmsService( ...@@ -45,13 +50,24 @@ SmsService::SmsService(
RenderFrameHost* host, RenderFrameHost* host,
mojo::PendingReceiver<blink::mojom::SmsReceiver> receiver) mojo::PendingReceiver<blink::mojom::SmsReceiver> receiver)
: SmsService(fetcher, : SmsService(fetcher,
nullptr,
host->GetLastCommittedOrigin(), host->GetLastCommittedOrigin(),
host, host,
std::move(receiver)) {} std::move(receiver)) {
bool needs_user_prompt =
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kWebOtpBackend) == switches::kWebOtpBackendSmsVerification;
if (needs_user_prompt) {
consent_handler_ = std::make_unique<PromptBasedUserConsentHandler>();
} else {
consent_handler_ = std::make_unique<NoopUserConsentHandler>();
}
}
SmsService::~SmsService() { SmsService::~SmsService() {
if (callback_) if (callback_)
Process(SmsStatus::kTimeout, base::nullopt); CompleteRequest(SmsStatus::kTimeout);
DCHECK(!callback_); DCHECK(!callback_);
} }
...@@ -72,6 +88,13 @@ void SmsService::Create( ...@@ -72,6 +88,13 @@ void SmsService::Create(
void SmsService::Receive(ReceiveCallback callback) { void SmsService::Receive(ReceiveCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// TODO(majidvp): The comment below seems incorrect. This flow is used for
// both prompted and unprompted backends so it is not clear if we should
// always cancel early. Also I don't believe that we are actually silently
// dropping the sms but in fact the logic cancels the request once
// an sms comes in and there is no delegate.
// This flow relies on the delegate to display an infobar for user // This flow relies on the delegate to display an infobar for user
// confirmation. Cancelling the call early if no delegate is available is // confirmation. Cancelling the call early if no delegate is available is
// easier to debug then silently dropping SMSes later on. // easier to debug then silently dropping SMSes later on.
...@@ -82,6 +105,7 @@ void SmsService::Receive(ReceiveCallback callback) { ...@@ -82,6 +105,7 @@ void SmsService::Receive(ReceiveCallback callback) {
return; return;
} }
// Abort the last request if there is we have not yet handled it.
if (callback_) { if (callback_) {
std::move(callback_).Run(SmsStatus::kCancelled, base::nullopt); std::move(callback_).Run(SmsStatus::kCancelled, base::nullopt);
fetcher_->Unsubscribe(origin_, this); fetcher_->Unsubscribe(origin_, this);
...@@ -90,9 +114,11 @@ void SmsService::Receive(ReceiveCallback callback) { ...@@ -90,9 +114,11 @@ void SmsService::Receive(ReceiveCallback callback) {
start_time_ = base::TimeTicks::Now(); start_time_ = base::TimeTicks::Now();
callback_ = std::move(callback); callback_ = std::move(callback);
// |one_time_code_| and prompt are still present from the previous // |one_time_code_| and prompt are still present from the previous request so
// request so a new subscription is unnecessary. // a new subscription is unnecessary. Note that it is only safe for us to use
if (prompt_open_) { // the in flight otp with the new request since both requests belong to the
// same origin.
if (consent_handler_->is_active()) {
// TODO(crbug.com/1024598): Add UMA histogram. // TODO(crbug.com/1024598): Add UMA histogram.
return; return;
} }
...@@ -102,29 +128,23 @@ void SmsService::Receive(ReceiveCallback callback) { ...@@ -102,29 +128,23 @@ void SmsService::Receive(ReceiveCallback callback) {
void SmsService::OnReceive(const std::string& one_time_code) { void SmsService::OnReceive(const std::string& one_time_code) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!one_time_code_); DCHECK(!one_time_code_);
DCHECK(!start_time_.is_null()); DCHECK(!start_time_.is_null());
auto now = base::TimeTicks::Now(); receive_time_ = base::TimeTicks::Now();
RecordSmsReceiveTime(now - start_time_); RecordSmsReceiveTime(receive_time_ - start_time_);
one_time_code_ = one_time_code; one_time_code_ = one_time_code;
if (base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( consent_handler_->RequestUserConsent(
switches::kWebOtpBackend) != render_frame_host(), origin_, one_time_code,
switches::kWebOtpBackendSmsVerification) { base::BindOnce(&SmsService::CompleteRequest,
Process(SmsStatus::kSuccess, one_time_code_); weak_ptr_factory_.GetWeakPtr()));
return;
}
receive_time_ = now;
OpenInfoBar(one_time_code);
} }
void SmsService::Abort() { void SmsService::Abort() {
DCHECK(callback_); DCHECK(callback_);
Process(SmsStatus::kAborted, base::nullopt); CompleteRequest(SmsStatus::kAborted);
} }
void SmsService::NavigationEntryCommitted( void SmsService::NavigationEntryCommitted(
...@@ -145,68 +165,39 @@ void SmsService::NavigationEntryCommitted( ...@@ -145,68 +165,39 @@ void SmsService::NavigationEntryCommitted(
} }
} }
void SmsService::OpenInfoBar(const std::string& one_time_code) { void SmsService::CompleteRequest(blink::mojom::SmsStatus status) {
WebContents* web_contents =
content::WebContents::FromRenderFrameHost(render_frame_host());
if (!web_contents->GetDelegate()) {
Process(SmsStatus::kCancelled, base::nullopt);
return;
}
prompt_open_ = true;
web_contents->GetDelegate()->CreateSmsPrompt(
render_frame_host(), origin_, one_time_code,
base::BindOnce(&SmsService::OnConfirm, weak_ptr_factory_.GetWeakPtr()),
base::BindOnce(&SmsService::OnCancel, weak_ptr_factory_.GetWeakPtr()));
}
void SmsService::Process(blink::mojom::SmsStatus status,
base::Optional<std::string> one_time_code) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(callback_);
std::move(callback_).Run(status, one_time_code);
CleanUp();
}
void SmsService::OnConfirm() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(one_time_code_); base::Optional<std::string> code = base::nullopt;
DCHECK(!receive_time_.is_null()); if (status == SmsStatus::kSuccess) {
RecordContinueOnSuccessTime(base::TimeTicks::Now() - receive_time_); DCHECK(one_time_code_);
code = one_time_code_;
prompt_open_ = false;
if (!callback_) {
// Cleanup since request has been aborted while prompt is up.
CleanUp();
return;
} }
Process(SmsStatus::kSuccess, one_time_code_);
}
void SmsService::OnCancel() { // Record ContinueOn timing values only if we are using an asynchronous
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // consent handler (i.e. showing user prompts).
if (consent_handler_->is_async()) {
// Record only when SMS has already been received. if (status == SmsStatus::kSuccess) {
DCHECK(!receive_time_.is_null()); DCHECK(!receive_time_.is_null());
RecordCancelOnSuccessTime(base::TimeTicks::Now() - receive_time_); RecordContinueOnSuccessTime(base::TimeTicks::Now() - receive_time_);
} else if (status == SmsStatus::kCancelled) {
prompt_open_ = false; DCHECK(!receive_time_.is_null());
RecordCancelOnSuccessTime(base::TimeTicks::Now() - receive_time_);
}
}
if (!callback_) { if (callback_) {
// Cleanup since request has been aborted while prompt is up. std::move(callback_).Run(status, code);
CleanUp();
return;
} }
Process(SmsStatus::kCancelled, base::nullopt);
CleanUp();
} }
void SmsService::CleanUp() { void SmsService::CleanUp() {
// Skip resetting |one_time_code_|, |sms| and |receive_time_| while prompt is // Skip resetting |one_time_code_|, |sms| and |receive_time_| while prompt is
// still open in case it needs to be returned to the next incoming request // still open in case it needs to be returned to the next incoming request
// upon prompt confirmation. // upon prompt confirmation.
if (!prompt_open_) { if (!consent_handler_->is_active()) {
one_time_code_.reset(); one_time_code_.reset();
receive_time_ = base::TimeTicks(); receive_time_ = base::TimeTicks();
} }
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "base/sequence_checker.h" #include "base/sequence_checker.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "content/browser/sms/sms_queue.h" #include "content/browser/sms/sms_queue.h"
#include "content/browser/sms/user_consent_handler.h"
#include "content/common/content_export.h" #include "content/common/content_export.h"
#include "content/public/browser/frame_service_base.h" #include "content/public/browser/frame_service_base.h"
#include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_receiver.h"
...@@ -44,6 +45,7 @@ class CONTENT_EXPORT SmsService ...@@ -44,6 +45,7 @@ class CONTENT_EXPORT SmsService
RenderFrameHost*, RenderFrameHost*,
mojo::PendingReceiver<blink::mojom::SmsReceiver>); mojo::PendingReceiver<blink::mojom::SmsReceiver>);
SmsService(SmsFetcher*, SmsService(SmsFetcher*,
std::unique_ptr<UserConsentHandler> consent_handler,
const url::Origin&, const url::Origin&,
RenderFrameHost*, RenderFrameHost*,
mojo::PendingReceiver<blink::mojom::SmsReceiver>); mojo::PendingReceiver<blink::mojom::SmsReceiver>);
...@@ -56,31 +58,27 @@ class CONTENT_EXPORT SmsService ...@@ -56,31 +58,27 @@ class CONTENT_EXPORT SmsService
// content::SmsQueue::Subscriber // content::SmsQueue::Subscriber
void OnReceive(const std::string& one_time_code) override; void OnReceive(const std::string& one_time_code) override;
// Completes the in-flight sms otp code request. Invokes the receive callback,
// if one is available, with the provided status code and the existing one
// time code.
void CompleteRequest(blink::mojom::SmsStatus);
protected: protected:
// content::WebContentsObserver: // content::WebContentsObserver:
void NavigationEntryCommitted( void NavigationEntryCommitted(
const content::LoadCommittedDetails& load_details) override; const content::LoadCommittedDetails& load_details) override;
private: private:
void OpenInfoBar(const std::string& one_time_code);
void Process(blink::mojom::SmsStatus,
base::Optional<std::string> one_time_code);
void CleanUp(); void CleanUp();
// Called when the user manually clicks the 'Enter code' button.
void OnConfirm();
// Called when the user manually dismisses the infobar.
void OnCancel();
// |fetcher_| is safe because all instances of SmsFetcher are owned // |fetcher_| is safe because all instances of SmsFetcher are owned
// by the browser context, which transitively (through RenderFrameHost) owns // by the browser context, which transitively (through RenderFrameHost) owns
// and outlives this class. // and outlives this class.
SmsFetcher* fetcher_; SmsFetcher* fetcher_;
std::unique_ptr<UserConsentHandler> consent_handler_;
const url::Origin origin_; const url::Origin origin_;
bool prompt_open_ = false;
ReceiveCallback callback_; ReceiveCallback callback_;
base::Optional<std::string> one_time_code_; base::Optional<std::string> one_time_code_;
base::TimeTicks start_time_; base::TimeTicks start_time_;
......
This diff is collapsed.
// Copyright 2020 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/test/mock_user_consent_handler.h"
namespace content {
MockUserConsentHandler::MockUserConsentHandler() = default;
MockUserConsentHandler::~MockUserConsentHandler() = default;
} // namespace content
\ No newline at end of file
// Copyright 2020 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.
#ifndef CONTENT_BROWSER_SMS_TEST_MOCK_USER_CONSENT_HANDLER_H_
#define CONTENT_BROWSER_SMS_TEST_MOCK_USER_CONSENT_HANDLER_H_
#include "base/macros.h"
#include "content/browser/sms/user_consent_handler.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace content {
class MockUserConsentHandler : public UserConsentHandler {
public:
MockUserConsentHandler();
~MockUserConsentHandler();
MOCK_METHOD(void,
RequestUserConsent,
(RenderFrameHost * frame_host,
const url::Origin& origin,
const std::string& one_time_code,
CompletionCallback on_complete),
(override));
MOCK_METHOD(bool, is_active, (), (const, override));
MOCK_METHOD(bool, is_async, (), (const, override));
};
} // namespace content
#endif // CONTENT_BROWSER_SMS_TEST_MOCK_USER_CONSENT_HANDLER_H_
\ No newline at end of file
// Copyright 2020 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/user_consent_handler.h"
#include "base/callback.h"
#include "content/browser/sms/sms_service.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_delegate.h"
using blink::mojom::SmsStatus;
namespace content {
NoopUserConsentHandler::~NoopUserConsentHandler() = default;
void NoopUserConsentHandler::RequestUserConsent(
RenderFrameHost* frame_host,
const url::Origin& origin,
const std::string& one_time_code,
CompletionCallback on_complete) {
std::move(on_complete).Run(SmsStatus::kSuccess);
}
bool NoopUserConsentHandler::is_active() const {
return false;
}
bool NoopUserConsentHandler::is_async() const {
return false;
}
PromptBasedUserConsentHandler::PromptBasedUserConsentHandler() = default;
PromptBasedUserConsentHandler::~PromptBasedUserConsentHandler() = default;
void PromptBasedUserConsentHandler::RequestUserConsent(
RenderFrameHost* frame_host,
const url::Origin& origin,
const std::string& one_time_code,
CompletionCallback on_complete) {
WebContents* web_contents =
content::WebContents::FromRenderFrameHost(frame_host);
if (!web_contents->GetDelegate()) {
std::move(on_complete).Run(SmsStatus::kCancelled);
return;
}
on_complete_ = std::move(on_complete);
is_prompt_open_ = true;
web_contents->GetDelegate()->CreateSmsPrompt(
frame_host, origin, one_time_code,
base::BindOnce(&PromptBasedUserConsentHandler::OnConfirm,
weak_ptr_factory_.GetWeakPtr()),
base::BindOnce(&PromptBasedUserConsentHandler::OnCancel,
weak_ptr_factory_.GetWeakPtr()));
}
bool PromptBasedUserConsentHandler::is_active() const {
return is_prompt_open_;
}
bool PromptBasedUserConsentHandler::is_async() const {
return true;
}
void PromptBasedUserConsentHandler::OnConfirm() {
is_prompt_open_ = false;
std::move(on_complete_).Run(SmsStatus::kSuccess);
}
void PromptBasedUserConsentHandler::OnCancel() {
is_prompt_open_ = false;
std::move(on_complete_).Run(SmsStatus::kCancelled);
}
} // namespace content
\ No newline at end of file
// Copyright 2020 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.
#ifndef CONTENT_BROWSER_SMS_USER_CONSENT_HANDLER_H_
#define CONTENT_BROWSER_SMS_USER_CONSENT_HANDLER_H_
#include "base/callback_forward.h"
#include "content/common/content_export.h"
#include "third_party/blink/public/mojom/sms/sms_receiver.mojom-shared.h"
#include "url/origin.h"
namespace content {
class RenderFrameHost;
using CompletionCallback = base::OnceCallback<void(blink::mojom::SmsStatus)>;
class CONTENT_EXPORT UserConsentHandler {
public:
virtual ~UserConsentHandler() = default;
// Ask for the user consent. Once the process is complete it invokes
// |on_complete| callback with the appropriate status.
virtual void RequestUserConsent(RenderFrameHost* frame_host,
const url::Origin& origin,
const std::string& one_time_code,
CompletionCallback on_complete) = 0;
// Returns true if it is still processing an inflight request.
// Note that this always returns false for not asynchronous handlers.
virtual bool is_active() const = 0;
// Returns true if this handler processes request asynchronously.
virtual bool is_async() const = 0;
};
class CONTENT_EXPORT NoopUserConsentHandler : public UserConsentHandler {
public:
~NoopUserConsentHandler() override;
void RequestUserConsent(RenderFrameHost* frame_host,
const url::Origin& origin,
const std::string& one_time_code,
CompletionCallback on_complete) override;
bool is_active() const override;
bool is_async() const override;
};
class CONTENT_EXPORT PromptBasedUserConsentHandler : public UserConsentHandler {
public:
PromptBasedUserConsentHandler();
~PromptBasedUserConsentHandler() override;
void RequestUserConsent(RenderFrameHost* frame_host,
const url::Origin& origin,
const std::string& one_time_code,
CompletionCallback on_complete) override;
bool is_active() const override;
bool is_async() const override;
void OnConfirm();
void OnCancel();
private:
bool is_prompt_open_{false};
CompletionCallback on_complete_;
base::WeakPtrFactory<PromptBasedUserConsentHandler> weak_ptr_factory_{this};
};
} // namespace content
#endif // CONTENT_BROWSER_SMS_USER_CONSENT_HANDLER_H_
\ No newline at end of file
// Copyright 2020 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/user_consent_handler.h"
#include "base/callback.h"
#include "base/test/bind_test_util.h"
#include "content/browser/sms/test/mock_sms_web_contents_delegate.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/test/navigation_simulator.h"
#include "content/public/test/test_renderer_host.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using std::string;
using ::testing::_;
using ::testing::ByMove;
using ::testing::Invoke;
using ::testing::NiceMock;
using ::testing::Return;
using ::testing::StrictMock;
using url::Origin;
namespace content {
namespace {
using blink::mojom::SmsStatus;
const char kTestUrl[] = "https://testing.test";
class PromptBasedUserConsentHandlerTest : public RenderViewHostTestHarness {
public:
void SetUp() override {
RenderViewHostTestHarness::SetUp();
WebContentsImpl* web_contents_impl =
reinterpret_cast<WebContentsImpl*>(web_contents());
web_contents_impl->SetDelegate(&delegate_);
}
void ExpectCreateSmsPrompt(RenderFrameHost* rfh,
const url::Origin& origin,
const std::string& one_time_code) {
EXPECT_CALL(delegate_, CreateSmsPrompt(rfh, origin, one_time_code, _, _))
.WillOnce(Invoke([=](RenderFrameHost*, const Origin& origin,
const std::string&, base::OnceClosure on_confirm,
base::OnceClosure on_cancel) {
confirm_callback_ = std::move(on_confirm);
dismiss_callback_ = std::move(on_cancel);
}));
}
void ExpectNoSmsPrompt() {
EXPECT_CALL(delegate_, CreateSmsPrompt(_, _, _, _, _)).Times(0);
}
void ConfirmPrompt() {
if (!confirm_callback_.is_null()) {
std::move(confirm_callback_).Run();
dismiss_callback_.Reset();
return;
}
FAIL() << "SmsInfobar not available";
}
void DismissPrompt() {
if (dismiss_callback_.is_null()) {
FAIL() << "SmsInfobar not available";
return;
}
std::move(dismiss_callback_).Run();
confirm_callback_.Reset();
}
private:
NiceMock<MockSmsWebContentsDelegate> delegate_;
base::OnceClosure confirm_callback_;
base::OnceClosure dismiss_callback_;
};
TEST_F(PromptBasedUserConsentHandlerTest, PromptsUser) {
NavigateAndCommit(GURL(kTestUrl));
const url::Origin& origin =
web_contents()->GetMainFrame()->GetLastCommittedOrigin();
base::RunLoop loop;
ExpectCreateSmsPrompt(main_rfh(), origin, "12345");
CompletionCallback callback;
PromptBasedUserConsentHandler consent_handler;
consent_handler.RequestUserConsent(main_rfh(), origin, "12345",
std::move(callback));
}
TEST_F(PromptBasedUserConsentHandlerTest, ConfirmInvokedCallback) {
NavigateAndCommit(GURL(kTestUrl));
const url::Origin& origin =
web_contents()->GetMainFrame()->GetLastCommittedOrigin();
ExpectCreateSmsPrompt(main_rfh(), origin, "12345");
PromptBasedUserConsentHandler consent_handler;
EXPECT_FALSE(consent_handler.is_active());
bool succeed;
auto callback = base::BindLambdaForTesting(
[&](SmsStatus status) { succeed = (status == SmsStatus::kSuccess); });
consent_handler.RequestUserConsent(main_rfh(), origin, "12345",
std::move(callback));
EXPECT_TRUE(consent_handler.is_active());
ConfirmPrompt();
EXPECT_FALSE(consent_handler.is_active());
EXPECT_TRUE(succeed);
}
TEST_F(PromptBasedUserConsentHandlerTest, CancelingInvokedCallback) {
NavigateAndCommit(GURL(kTestUrl));
const url::Origin& origin =
web_contents()->GetMainFrame()->GetLastCommittedOrigin();
ExpectCreateSmsPrompt(main_rfh(), origin, "12345");
PromptBasedUserConsentHandler consent_handler;
EXPECT_FALSE(consent_handler.is_active());
bool cancelled;
auto callback = base::BindLambdaForTesting(
[&](SmsStatus status) { cancelled = (status == SmsStatus::kCancelled); });
consent_handler.RequestUserConsent(main_rfh(), origin, "12345",
std::move(callback));
EXPECT_TRUE(consent_handler.is_active());
DismissPrompt();
EXPECT_FALSE(consent_handler.is_active());
EXPECT_TRUE(cancelled);
}
TEST_F(PromptBasedUserConsentHandlerTest, CancelsWhenNoDelegate) {
NavigateAndCommit(GURL(kTestUrl));
const url::Origin& origin =
web_contents()->GetMainFrame()->GetLastCommittedOrigin();
WebContentsImpl* web_contents_impl =
reinterpret_cast<WebContentsImpl*>(web_contents());
web_contents_impl->SetDelegate(nullptr);
ExpectNoSmsPrompt();
PromptBasedUserConsentHandler consent_handler;
bool cancelled;
auto callback = base::BindLambdaForTesting(
[&](SmsStatus status) { cancelled = (status == SmsStatus::kCancelled); });
consent_handler.RequestUserConsent(main_rfh(), origin, "12345",
std::move(callback));
EXPECT_TRUE(cancelled);
}
} // namespace
} // namespace content
\ No newline at end of file
...@@ -83,6 +83,8 @@ jumbo_static_library("test_support") { ...@@ -83,6 +83,8 @@ jumbo_static_library("test_support") {
"../browser/sms/test/mock_sms_provider.h", "../browser/sms/test/mock_sms_provider.h",
"../browser/sms/test/mock_sms_web_contents_delegate.cc", "../browser/sms/test/mock_sms_web_contents_delegate.cc",
"../browser/sms/test/mock_sms_web_contents_delegate.h", "../browser/sms/test/mock_sms_web_contents_delegate.h",
"../browser/sms/test/mock_user_consent_handler.cc",
"../browser/sms/test/mock_user_consent_handler.h",
"../browser/web_package/mock_signed_exchange_handler.cc", "../browser/web_package/mock_signed_exchange_handler.cc",
"../browser/web_package/mock_signed_exchange_handler.h", "../browser/web_package/mock_signed_exchange_handler.h",
"../browser/web_package/mock_web_bundle_reader_factory.cc", "../browser/web_package/mock_web_bundle_reader_factory.cc",
...@@ -1921,6 +1923,7 @@ test("content_unittests") { ...@@ -1921,6 +1923,7 @@ test("content_unittests") {
"../browser/sms/sms_fetcher_impl_unittest.cc", "../browser/sms/sms_fetcher_impl_unittest.cc",
"../browser/sms/sms_parser_unittest.cc", "../browser/sms/sms_parser_unittest.cc",
"../browser/sms/sms_service_unittest.cc", "../browser/sms/sms_service_unittest.cc",
"../browser/sms/user_consent_handler_unittest.cc",
"../browser/speech/tts_controller_unittest.cc", "../browser/speech/tts_controller_unittest.cc",
"../browser/startup_task_runner_unittest.cc", "../browser/startup_task_runner_unittest.cc",
"../browser/storage_partition_impl_map_unittest.cc", "../browser/storage_partition_impl_map_unittest.cc",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment