blob: a90a37dcb4edf93934dc81f748775d243e20aee3 [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/callback.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/sms/sms_parser.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_client.h"
namespace content {
const char kSmsFetcherImplKeyName[] = "sms_fetcher";
SmsFetcherImpl::SmsFetcherImpl(BrowserContext* context, SmsProvider* provider)
: context_(context), provider_(provider) {
if (provider_)
provider_->AddObserver(this);
}
SmsFetcherImpl::~SmsFetcherImpl() {
if (provider_)
provider_->RemoveObserver(this);
}
// static
SmsFetcher* SmsFetcher::Get(BrowserContext* context) {
if (!context->GetUserData(kSmsFetcherImplKeyName)) {
auto fetcher = std::make_unique<SmsFetcherImpl>(
context, BrowserMainLoop::GetInstance()->GetSmsProvider());
context->SetUserData(kSmsFetcherImplKeyName, std::move(fetcher));
}
return static_cast<SmsFetcherImpl*>(
context->GetUserData(kSmsFetcherImplKeyName));
}
// TODO(crbug.com/1015645): Add implementation.
void SmsFetcherImpl::Subscribe(const url::Origin& origin,
SmsQueue::Subscriber* subscriber) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
NOTIMPLEMENTED();
}
void SmsFetcherImpl::Subscribe(const url::Origin& origin,
SmsQueue::Subscriber* subscriber,
RenderFrameHost* render_frame_host) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(subscriber);
DCHECK(render_frame_host);
// Should not be called multiple times for the same subscriber and origin.
DCHECK(!subscribers_.HasSubscriber(origin, subscriber));
subscribers_.Push(origin, subscriber);
// Fetches a remote SMS.
GetContentClient()->browser()->FetchRemoteSms(
context_, origin,
base::BindOnce(&SmsFetcherImpl::OnRemote,
weak_ptr_factory_.GetWeakPtr()));
// Fetches a local SMS.
if (provider_)
provider_->Retrieve(render_frame_host);
}
void SmsFetcherImpl::Unsubscribe(const url::Origin& origin,
SmsQueue::Subscriber* subscriber) {
// Unsubscribe does not make a call to the provider because currently there
// is no mechanism to cancel a subscription.
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
subscribers_.Remove(origin, subscriber);
}
bool SmsFetcherImpl::Notify(const url::Origin& origin,
const std::string& one_time_code) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// The received OTP is returned to the first subscriber for the origin.
auto* subscriber = subscribers_.Pop(origin);
if (!subscriber)
return false;
subscriber->OnReceive(one_time_code);
return true;
}
void SmsFetcherImpl::OnRemote(base::Optional<std::string> sms) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!sms)
return;
// TODO(yigu): We should log when the sms cannot be parsed similar to local
// SMSes.
SmsParser::Result result = SmsParser::Parse(*sms);
if (!result.IsValid())
return;
Notify(result.origin, result.one_time_code);
}
bool SmsFetcherImpl::OnReceive(const url::Origin& origin,
const std::string& one_time_code) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return Notify(origin, one_time_code);
}
void SmsFetcherImpl::NotifyParsingFailure(SmsParser::SmsParsingStatus status) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
subscribers_.NotifyParsingFailure(status);
}
bool SmsFetcherImpl::HasSubscribers() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return subscribers_.HasSubscribers();
}
} // namespace content