Skip to content

Commit 2e5be59

Browse files
committed
web-nfc: Join NDEFReader and NDEFWriter
refers to w3c/web-nfc#601 Bug: 1131141 Change-Id: I8cc2ce053e5bb43c0fa5b299bdaf5cb5317bf859
1 parent 5a4e760 commit 2e5be59

27 files changed

+307
-440
lines changed

third_party/blink/renderer/bindings/generated_in_modules.gni

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1727,8 +1727,6 @@ generated_interface_sources_in_modules = [
17271727
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_ndef_reading_event.h",
17281728
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_ndef_record.cc",
17291729
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_ndef_record.h",
1730-
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_ndef_writer.cc",
1731-
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_ndef_writer.h",
17321730
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_network_information.cc",
17331731
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_network_information.h",
17341732
"$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_notification.cc",

third_party/blink/renderer/bindings/idl_in_modules.gni

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,6 @@ static_idl_files_in_modules = get_path_info(
406406
"//third_party/blink/renderer/modules/nfc/ndef_record_init.idl",
407407
"//third_party/blink/renderer/modules/nfc/ndef_scan_options.idl",
408408
"//third_party/blink/renderer/modules/nfc/ndef_write_options.idl",
409-
"//third_party/blink/renderer/modules/nfc/ndef_writer.idl",
410409
"//third_party/blink/renderer/modules/notifications/get_notification_options.idl",
411410
"//third_party/blink/renderer/modules/notifications/notification.idl",
412411
"//third_party/blink/renderer/modules/notifications/notification_action.idl",

third_party/blink/renderer/modules/nfc/BUILD.gn

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ blink_modules_sources("nfc") {
1414
"ndef_reading_event.h",
1515
"ndef_record.cc",
1616
"ndef_record.h",
17-
"ndef_writer.cc",
18-
"ndef_writer.h",
1917
"nfc_proxy.cc",
2018
"nfc_proxy.h",
2119
"nfc_type_converters.cc",

third_party/blink/renderer/modules/nfc/idls.gni

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ modules_idl_files = [
77
"ndef_record.idl",
88
"ndef_reader.idl",
99
"ndef_reading_event.idl",
10-
"ndef_writer.idl",
1110
]
1211

1312
modules_dictionary_idl_files = [

third_party/blink/renderer/modules/nfc/ndef_reader.cc

Lines changed: 183 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@
66

77
#include <utility>
88

9+
#include "mojo/public/cpp/bindings/callback_helpers.h"
910
#include "services/device/public/mojom/nfc.mojom-blink.h"
10-
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
1111
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
12+
#include "third_party/blink/renderer/bindings/modules/v8/string_or_array_buffer_or_array_buffer_view_or_ndef_message_init.h"
1213
#include "third_party/blink/renderer/bindings/modules/v8/v8_ndef_scan_options.h"
14+
#include "third_party/blink/renderer/bindings/modules/v8/v8_ndef_write_options.h"
1315
#include "third_party/blink/renderer/core/dom/abort_signal.h"
1416
#include "third_party/blink/renderer/core/dom/dom_exception.h"
1517
#include "third_party/blink/renderer/core/events/error_event.h"
@@ -19,6 +21,7 @@
1921
#include "third_party/blink/renderer/modules/nfc/ndef_message.h"
2022
#include "third_party/blink/renderer/modules/nfc/ndef_reading_event.h"
2123
#include "third_party/blink/renderer/modules/nfc/nfc_proxy.h"
24+
#include "third_party/blink/renderer/modules/nfc/nfc_type_converters.h"
2225
#include "third_party/blink/renderer/modules/nfc/nfc_utils.h"
2326
#include "third_party/blink/renderer/modules/permissions/permission_utils.h"
2427
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
@@ -114,29 +117,19 @@ ScriptPromise NDEFReader::scan(ScriptState* script_state,
114117
// to reader.[[Signal]]:
115118
if (options->hasSignal()) {
116119
options->signal()->AddAlgorithm(
117-
WTF::Bind(&NDEFReader::Abort, WrapPersistent(this)));
120+
WTF::Bind(&NDEFReader::ReadAbort, WrapPersistent(this)));
118121
}
119122

120123
GetPermissionService()->RequestPermission(
121124
CreatePermissionDescriptor(PermissionName::NFC),
122125
LocalFrame::HasTransientUserActivation(frame),
123-
WTF::Bind(&NDEFReader::OnRequestPermission, WrapPersistent(this),
126+
WTF::Bind(&NDEFReader::ReadOnRequestPermission, WrapPersistent(this),
124127
WrapPersistent(options)));
125128
return resolver_->Promise();
126129
}
127130

128-
PermissionService* NDEFReader::GetPermissionService() {
129-
if (!permission_service_.is_bound()) {
130-
ConnectToPermissionService(
131-
GetExecutionContext(),
132-
permission_service_.BindNewPipeAndPassReceiver(
133-
GetExecutionContext()->GetTaskRunner(TaskType::kMiscPlatformAPI)));
134-
}
135-
return permission_service_.get();
136-
}
137-
138-
void NDEFReader::OnRequestPermission(const NDEFScanOptions* options,
139-
PermissionStatus status) {
131+
void NDEFReader::ReadOnRequestPermission(const NDEFScanOptions* options,
132+
PermissionStatus status) {
140133
if (!resolver_) {
141134
has_pending_scan_request_ = false;
142135
return;
@@ -163,10 +156,10 @@ void NDEFReader::OnRequestPermission(const NDEFScanOptions* options,
163156

164157
GetNfcProxy()->StartReading(
165158
this,
166-
WTF::Bind(&NDEFReader::OnScanRequestCompleted, WrapPersistent(this)));
159+
WTF::Bind(&NDEFReader::ScanOnRequestCompleted, WrapPersistent(this)));
167160
}
168161

169-
void NDEFReader::OnScanRequestCompleted(
162+
void NDEFReader::ScanOnRequestCompleted(
170163
device::mojom::blink::NDEFErrorPtr error) {
171164
has_pending_scan_request_ = false;
172165
if (!resolver_)
@@ -182,14 +175,6 @@ void NDEFReader::OnScanRequestCompleted(
182175
resolver_.Clear();
183176
}
184177

185-
void NDEFReader::Trace(Visitor* visitor) const {
186-
visitor->Trace(permission_service_);
187-
visitor->Trace(resolver_);
188-
EventTargetWithInlineData::Trace(visitor);
189-
ActiveScriptWrappable::Trace(visitor);
190-
ExecutionContextLifecycleObserver::Trace(visitor);
191-
}
192-
193178
void NDEFReader::OnReading(const String& serial_number,
194179
const device::mojom::blink::NDEFMessage& message) {
195180
DCHECK(GetNfcProxy()->IsReading(this));
@@ -204,19 +189,6 @@ void NDEFReader::OnError(const String& message) {
204189
DispatchEvent(*event);
205190
}
206191

207-
void NDEFReader::OnMojoConnectionError() {
208-
// If |resolver_| has already settled this rejection is silently ignored.
209-
if (resolver_) {
210-
resolver_->Reject(NDEFErrorTypeToDOMException(
211-
device::mojom::blink::NDEFErrorType::NOT_SUPPORTED,
212-
kNotSupportedOrPermissionDenied));
213-
resolver_.Clear();
214-
}
215-
216-
// Dispatches an error event.
217-
OnError(kNotSupportedOrPermissionDenied);
218-
}
219-
220192
void NDEFReader::ContextDestroyed() {
221193
// If |resolver_| has already settled this rejection is silently ignored.
222194
if (resolver_) {
@@ -228,7 +200,7 @@ void NDEFReader::ContextDestroyed() {
228200
GetNfcProxy()->StopReading(this);
229201
}
230202

231-
void NDEFReader::Abort() {
203+
void NDEFReader::ReadAbort() {
232204
if (resolver_) {
233205
resolver_->Reject(MakeGarbageCollected<DOMException>(
234206
DOMExceptionCode::kAbortError, "The NFC operation was cancelled."));
@@ -238,9 +210,181 @@ void NDEFReader::Abort() {
238210
GetNfcProxy()->StopReading(this);
239211
}
240212

213+
// https://w3c.github.io/web-nfc/#writing-content
214+
// https://w3c.github.io/web-nfc/#the-write-method
215+
ScriptPromise NDEFReader::write(ScriptState* script_state,
216+
const NDEFMessageSource& write_message,
217+
const NDEFWriteOptions* options,
218+
ExceptionState& exception_state) {
219+
LocalDOMWindow* window = script_state->ContextIsValid()
220+
? LocalDOMWindow::From(script_state)
221+
: nullptr;
222+
// https://w3c.github.io/web-nfc/#security-policies
223+
// WebNFC API must be only accessible from top level browsing context.
224+
if (!window || !window->GetFrame()->IsMainFrame()) {
225+
exception_state.ThrowDOMException(DOMExceptionCode::kNotAllowedError,
226+
"NFC interfaces are only avaliable "
227+
"in a top-level browsing context");
228+
return ScriptPromise();
229+
}
230+
231+
if (options->hasSignal() && options->signal()->aborted()) {
232+
// If signal’s aborted flag is set, then reject p with an "AbortError"
233+
// DOMException and return p.
234+
exception_state.ThrowDOMException(DOMExceptionCode::kAbortError,
235+
"The NFC operation was cancelled.");
236+
return ScriptPromise();
237+
}
238+
239+
// Step 11.2: Run "create NDEF message", if this throws an exception,
240+
// reject p with that exception and abort these steps.
241+
NDEFMessage* ndef_message =
242+
NDEFMessage::Create(window, write_message, exception_state);
243+
if (exception_state.HadException()) {
244+
return ScriptPromise();
245+
}
246+
247+
auto message = device::mojom::blink::NDEFMessage::From(ndef_message);
248+
DCHECK(message);
249+
250+
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
251+
requests_.insert(resolver);
252+
InitNfcProxyIfNeeded();
253+
GetPermissionService()->RequestPermission(
254+
CreatePermissionDescriptor(PermissionName::NFC),
255+
LocalFrame::HasTransientUserActivation(window->GetFrame()),
256+
WTF::Bind(&NDEFReader::WriteOnRequestPermission, WrapPersistent(this),
257+
WrapPersistent(resolver), WrapPersistent(options),
258+
std::move(message)));
259+
260+
return resolver->Promise();
261+
}
262+
263+
void NDEFReader::WriteOnRequestPermission(
264+
ScriptPromiseResolver* resolver,
265+
const NDEFWriteOptions* options,
266+
device::mojom::blink::NDEFMessagePtr message,
267+
PermissionStatus status) {
268+
if (status != PermissionStatus::GRANTED) {
269+
resolver->Reject(MakeGarbageCollected<DOMException>(
270+
DOMExceptionCode::kNotAllowedError, "NFC permission request denied."));
271+
return;
272+
}
273+
274+
if (options->hasSignal() && options->signal()->aborted()) {
275+
resolver->Reject(MakeGarbageCollected<DOMException>(
276+
DOMExceptionCode::kAbortError, "The NFC operation was cancelled."));
277+
return;
278+
}
279+
280+
// If signal is not null, then add the abort steps to signal.
281+
if (options->hasSignal() && !options->signal()->aborted()) {
282+
options->signal()->AddAlgorithm(WTF::Bind(&NDEFReader::WriteAbort,
283+
WrapPersistent(this),
284+
WrapPersistent(resolver)));
285+
}
286+
287+
UseCounter::Count(GetExecutionContext(), WebFeature::kWebNfcNdefWriterWrite);
288+
// TODO(https://crbug.com/994936) remove when origin trial is complete.
289+
UseCounter::Count(GetExecutionContext(), WebFeature::kWebNfcAPI);
290+
291+
auto callback = WTF::Bind(&NDEFReader::WriteOnRequestCompleted,
292+
WrapPersistent(this), WrapPersistent(resolver));
293+
nfc_proxy_->Push(std::move(message),
294+
device::mojom::blink::NDEFWriteOptions::From(options),
295+
std::move(callback));
296+
}
297+
298+
void NDEFReader::WriteOnRequestCompleted(
299+
ScriptPromiseResolver* resolver,
300+
device::mojom::blink::NDEFErrorPtr error) {
301+
DCHECK(requests_.Contains(resolver));
302+
303+
requests_.erase(resolver);
304+
305+
if (error.is_null()) {
306+
resolver->Resolve();
307+
} else {
308+
resolver->Reject(
309+
NDEFErrorTypeToDOMException(error->error_type, error->error_message));
310+
}
311+
}
312+
313+
void NDEFReader::WriteAbort(ScriptPromiseResolver* resolver) {
314+
// |nfc_proxy_| could be null on Mojo connection failure, simply ignore the
315+
// abort request in this case.
316+
if (!nfc_proxy_)
317+
return;
318+
319+
// OnRequestCompleted() should always be called whether the push operation is
320+
// cancelled successfully or not. So do nothing for the cancelled callback.
321+
nfc_proxy_->CancelPush(device::mojom::blink::NFC::CancelPushCallback());
322+
}
323+
324+
void NDEFReader::InitNfcProxyIfNeeded() {
325+
// Init NfcProxy if needed.
326+
if (nfc_proxy_) {
327+
nfc_proxy_->AddWriter(this);
328+
return;
329+
}
330+
331+
nfc_proxy_ = NFCProxy::From(*To<LocalDOMWindow>(GetExecutionContext()));
332+
DCHECK(nfc_proxy_);
333+
334+
// Add the writer to proxy's writer list for mojo connection error
335+
// notification.
336+
nfc_proxy_->AddWriter(this);
337+
}
338+
241339
NFCProxy* NDEFReader::GetNfcProxy() const {
242340
DCHECK(GetExecutionContext());
243341
return NFCProxy::From(*To<LocalDOMWindow>(GetExecutionContext()));
244342
}
245343

344+
void NDEFReader::Trace(Visitor* visitor) const {
345+
visitor->Trace(permission_service_);
346+
visitor->Trace(nfc_proxy_);
347+
visitor->Trace(resolver_);
348+
visitor->Trace(requests_);
349+
EventTargetWithInlineData::Trace(visitor);
350+
ActiveScriptWrappable::Trace(visitor);
351+
ExecutionContextLifecycleObserver::Trace(visitor);
352+
}
353+
354+
PermissionService* NDEFReader::GetPermissionService() {
355+
if (!permission_service_.is_bound()) {
356+
ConnectToPermissionService(
357+
GetExecutionContext(),
358+
permission_service_.BindNewPipeAndPassReceiver(
359+
GetExecutionContext()->GetTaskRunner(TaskType::kMiscPlatformAPI)));
360+
}
361+
return permission_service_.get();
362+
}
363+
364+
void NDEFReader::ReadOnMojoConnectionError() {
365+
// If |resolver_| has already settled this rejection is silently ignored.
366+
if (resolver_) {
367+
resolver_->Reject(NDEFErrorTypeToDOMException(
368+
device::mojom::blink::NDEFErrorType::NOT_SUPPORTED,
369+
kNotSupportedOrPermissionDenied));
370+
resolver_.Clear();
371+
}
372+
373+
// Dispatches an error event.
374+
OnError(kNotSupportedOrPermissionDenied);
375+
}
376+
377+
void NDEFReader::WriteOnMojoConnectionError() {
378+
nfc_proxy_.Clear();
379+
380+
// If the mojo connection breaks, all push requests will be rejected with a
381+
// default error.
382+
for (ScriptPromiseResolver* resolver : requests_) {
383+
resolver->Reject(NDEFErrorTypeToDOMException(
384+
device::mojom::blink::NDEFErrorType::NOT_SUPPORTED,
385+
kNotSupportedOrPermissionDenied));
386+
}
387+
requests_.clear();
388+
}
389+
246390
} // namespace blink

0 commit comments

Comments
 (0)