blob: 34c5b3d100cf14e5d341a3a6192c7db792cdc514 [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 <utility>
#include "third_party/blink/renderer/modules/sms/sms_receiver.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/sms/sms_receiver.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/modules/sms/sms.h"
#include "third_party/blink/renderer/modules/sms/sms_metrics.h"
#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace blink {
SMSReceiver::SMSReceiver(ExecutionContext* context) : ContextClient(context) {}
ScriptPromise SMSReceiver::receive(ScriptState* script_state,
const SMSReceiverOptions* options) {
ExecutionContext* context = ExecutionContext::From(script_state);
DCHECK(context->IsContextThread());
LocalFrame* frame = GetFrame();
if (!frame->IsMainFrame() && frame->IsCrossOriginSubframe()) {
return ScriptPromise::RejectWithDOMException(
script_state, MakeGarbageCollected<DOMException>(
DOMExceptionCode::kNotAllowedError,
"Must have the same origin as the top-level frame."));
}
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
requests_.insert(resolver);
// See https://bit.ly/2S0zRAS for task types.
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
GetExecutionContext()->GetTaskRunner(TaskType::kMiscPlatformAPI);
if (!service_) {
GetExecutionContext()->GetBrowserInterfaceBroker().GetInterface(
service_.BindNewPipeAndPassReceiver(task_runner));
service_.set_disconnect_handler(WTF::Bind(
&SMSReceiver::OnSMSReceiverConnectionError, WrapWeakPersistent(this)));
}
service_->Receive(
WTF::Bind(&SMSReceiver::OnReceive, WrapPersistent(this),
WrapPersistent(resolver), base::TimeTicks::Now()));
return resolver->Promise();
}
SMSReceiver::~SMSReceiver() = default;
void SMSReceiver::OnReceive(ScriptPromiseResolver* resolver,
base::TimeTicks start_time,
mojom::blink::SmsStatus status,
const WTF::String& sms) {
requests_.erase(resolver);
ukm::SourceId source_id = GetDocument()->UkmSourceID();
ukm::UkmRecorder* recorder = GetDocument()->UkmRecorder();
if (status == mojom::blink::SmsStatus::kTimeout) {
resolver->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kTimeoutError, "SMSReceiver timed out."));
RecordSMSOutcome(SMSReceiverOutcome::kTimeout, source_id, recorder);
return;
} else if (status == mojom::blink::SmsStatus::kCancelled) {
resolver->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kAbortError, "SMSReceiver was aborted."));
RecordSMSCancelTime(base::TimeTicks::Now() - start_time);
RecordSMSOutcome(SMSReceiverOutcome::kCancelled, source_id, recorder);
return;
}
RecordSMSSuccessTime(base::TimeTicks::Now() - start_time);
RecordSMSOutcome(SMSReceiverOutcome::kSuccess, source_id, recorder);
resolver->Resolve(MakeGarbageCollected<blink::SMS>(sms));
}
void SMSReceiver::OnSMSReceiverConnectionError() {
service_.reset();
for (ScriptPromiseResolver* request : requests_) {
request->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kNotFoundError, "SMSReceiver not available."));
RecordSMSOutcome(SMSReceiverOutcome::kConnectionError,
GetDocument()->UkmSourceID(),
GetDocument()->UkmRecorder());
}
requests_.clear();
}
void SMSReceiver::Trace(Visitor* visitor) {
ScriptWrappable::Trace(visitor);
ContextClient::Trace(visitor);
visitor->Trace(requests_);
}
} // namespace blink