Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(532)

Unified Diff: third_party/WebKit/Source/modules/nfc/NFC.cpp

Issue 1759373003: [webnfc] Implement nfc.watch in blink nfc module. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@implement_nfc_push_in_android
Patch Set: Rebased to master Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« device/nfc/nfc.mojom ('K') | « third_party/WebKit/Source/modules/nfc/NFC.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/WebKit/Source/modules/nfc/NFC.cpp
diff --git a/third_party/WebKit/Source/modules/nfc/NFC.cpp b/third_party/WebKit/Source/modules/nfc/NFC.cpp
index ac7a95cf4a12254dd5d38df80fa35a226e8a9eff..0ac0c5255e07d020beded05f3ad587d73501e560 100644
--- a/third_party/WebKit/Source/modules/nfc/NFC.cpp
+++ b/third_party/WebKit/Source/modules/nfc/NFC.cpp
@@ -15,6 +15,7 @@
#include "modules/nfc/NFCError.h"
#include "modules/nfc/NFCMessage.h"
#include "modules/nfc/NFCPushOptions.h"
+#include "modules/nfc/NFCWatchOptions.h"
#include "platform/mojo/MojoHelper.h"
#include "public/platform/InterfaceProvider.h"
#include "public/platform/Platform.h"
@@ -36,9 +37,13 @@ using device::nfc::mojom::blink::NFCMessagePtr;
using device::nfc::mojom::blink::NFCRecord;
using device::nfc::mojom::blink::NFCRecordPtr;
using device::nfc::mojom::blink::NFCRecordType;
+using device::nfc::mojom::blink::NFCRecordTypeFilter;
using device::nfc::mojom::blink::NFCPushOptions;
using device::nfc::mojom::blink::NFCPushOptionsPtr;
using device::nfc::mojom::blink::NFCPushTarget;
+using device::nfc::mojom::blink::NFCWatchMode;
+using device::nfc::mojom::blink::NFCWatchOptions;
+using device::nfc::mojom::blink::NFCWatchOptionsPtr;
NFCPushTarget toNFCPushTarget(const WTF::String& target) {
if (target == "tag")
@@ -70,6 +75,17 @@ NFCRecordType toNFCRecordType(const WTF::String& recordType) {
return NFCRecordType::EMPTY;
}
+NFCWatchMode toNFCWatchMode(const WTF::String& watchMode) {
+ if (watchMode == "web-nfc-only")
+ return NFCWatchMode::WEBNFC_ONLY;
+
+ if (watchMode == "any")
+ return NFCWatchMode::ANY;
+
+ NOTREACHED();
+ return NFCWatchMode::WEBNFC_ONLY;
+}
+
// https://w3c.github.io/web-nfc/#creating-web-nfc-message Step 2.1
// If NFCRecord type is not provided, deduce NFCRecord type from JS data type:
// String or Number => 'text' record
@@ -302,6 +318,32 @@ struct TypeConverter<NFCPushOptionsPtr, blink::NFCPushOptions> {
}
};
+template <>
+struct TypeConverter<NFCWatchOptionsPtr, blink::NFCWatchOptions> {
+ static NFCWatchOptionsPtr Convert(
+ const blink::NFCWatchOptions& watchOptions) {
+ // https://w3c.github.io/web-nfc/#the-nfcwatchoptions-dictionary
+ // Default values for NFCWatchOptions dictionary are:
+ // url = "", recordType = null, mediaType = "", mode = "web-nfc-only"
+ NFCWatchOptionsPtr watchOptionsPtr = NFCWatchOptions::New();
+ watchOptionsPtr->url = watchOptions.url();
+ watchOptionsPtr->media_type = watchOptions.mediaType();
+
+ if (watchOptions.hasMode())
+ watchOptionsPtr->mode = toNFCWatchMode(watchOptions.mode());
+ else
+ watchOptionsPtr->mode = NFCWatchMode::WEBNFC_ONLY;
+
+ if (watchOptions.hasRecordType()) {
+ watchOptionsPtr->record_filter = NFCRecordTypeFilter::New();
+ watchOptionsPtr->record_filter->record_type =
+ toNFCRecordType(watchOptions.recordType());
+ }
+
+ return watchOptionsPtr;
+ }
+};
+
} // namespace mojo
namespace blink {
@@ -426,6 +468,96 @@ bool setURL(const String& origin,
return originURL.isValid();
}
+String toNFCRecordType(const device::nfc::mojom::blink::NFCRecordType& type) {
+ switch (type) {
+ case device::nfc::mojom::blink::NFCRecordType::TEXT:
+ return "text";
+ case device::nfc::mojom::blink::NFCRecordType::URL:
+ return "url";
+ case device::nfc::mojom::blink::NFCRecordType::JSON:
+ return "json";
+ case device::nfc::mojom::blink::NFCRecordType::OPAQUE_RECORD:
+ return "opaque";
+ case device::nfc::mojom::blink::NFCRecordType::EMPTY:
+ return "empty";
+ }
+
+ NOTREACHED();
+ return String();
+}
+
+v8::Local<v8::Value> toV8(const device::nfc::mojom::blink::NFCRecordPtr& record,
+ ScriptState* scriptState) {
+ switch (record->record_type) {
+ case device::nfc::mojom::blink::NFCRecordType::TEXT:
+ case device::nfc::mojom::blink::NFCRecordType::URL:
+ case device::nfc::mojom::blink::NFCRecordType::JSON: {
+ String stringData;
+ if (!record->data.isEmpty()) {
+ stringData = String::fromUTF8WithLatin1Fallback(
+ static_cast<unsigned char*>(&record->data.first()),
+ record->data.size());
+ }
+
+ if (record->record_type ==
+ device::nfc::mojom::blink::NFCRecordType::JSON) {
+ return v8::JSON::Parse(scriptState->isolate(),
+ v8String(scriptState->isolate(), stringData))
+ .ToLocalChecked();
+ }
+
+ return v8String(scriptState->isolate(), stringData);
+ }
+
+ case device::nfc::mojom::blink::NFCRecordType::OPAQUE_RECORD: {
+ if (!record->data.isEmpty()) {
+ DOMArrayBuffer* buffer = DOMArrayBuffer::create(
+ static_cast<void*>(&record->data.first()), record->data.size());
+ return toV8(buffer, scriptState->context()->Global(),
+ scriptState->isolate());
+ }
+
+ return v8::Null(scriptState->isolate());
+ }
+
+ case device::nfc::mojom::blink::NFCRecordType::EMPTY:
+ return v8::Null(scriptState->isolate());
+ }
+
+ NOTREACHED();
+ return v8::Local<v8::Value>();
+}
+
+NFCRecord toNFCRecord(const device::nfc::mojom::blink::NFCRecordPtr& record,
+ ScriptState* scriptState) {
+ NFCRecord nfcRecord;
+ nfcRecord.setMediaType(record->media_type);
+ nfcRecord.setRecordType(toNFCRecordType(record->record_type));
+ nfcRecord.setData(ScriptValue(scriptState, toV8(record, scriptState)));
haraken 2016/11/22 02:38:14 Would you help me understand why you need to pass
shalamov 2016/11/22 12:50:41 This is a helper function that converts from mojom
+ return nfcRecord;
+}
+
+NFCMessage toNFCMessage(const device::nfc::mojom::blink::NFCMessagePtr& message,
+ ScriptState* scriptState) {
+ NFCMessage nfcMessage;
+ nfcMessage.setURL(message->url);
+ blink::HeapVector<NFCRecord> records;
+ for (size_t i = 0; i < message->data.size(); ++i)
+ records.append(toNFCRecord(message->data[i], scriptState));
+ nfcMessage.setData(records);
+ return nfcMessage;
+}
+
+size_t getNFCMessageSize(
+ const device::nfc::mojom::blink::NFCMessagePtr& message) {
+ size_t messageSize = message->url.charactersSizeInBytes();
+ for (size_t i = 0; i < message->data.size(); ++i) {
+ messageSize += message->data[i]->media_type.charactersSizeInBytes();
+ messageSize += message->data[i]->data.size();
+ }
+ return messageSize;
+}
+
} // anonymous namespace
NFC::NFC(LocalFrame* frame)
@@ -457,25 +589,22 @@ void NFC::dispose() {
void NFC::contextDestroyed() {
m_nfc.reset();
m_requests.clear();
+ m_callbacks.clear();
}
// https://w3c.github.io/web-nfc/#writing-or-pushing-content
+// https://w3c.github.io/web-nfc/#dom-nfc-push
ScriptPromise NFC::push(ScriptState* scriptState,
const NFCPushMessage& pushMessage,
const NFCPushOptions& options) {
- String errorMessage;
- if (!scriptState->getExecutionContext()->isSecureContext(errorMessage))
- return ScriptPromise::rejectWithDOMException(
- scriptState, DOMException::create(SecurityError, errorMessage));
+ ScriptPromise promise = rejectIfNotSupported(scriptState);
+ if (!promise.isEmpty())
+ return promise;
DOMException* exception = isValidNFCPushMessage(pushMessage);
if (exception)
return ScriptPromise::rejectWithDOMException(scriptState, exception);
- if (!m_nfc)
- return ScriptPromise::rejectWithDOMException(
- scriptState, DOMException::create(NotSupportedError));
-
device::nfc::mojom::blink::NFCMessagePtr message =
device::nfc::mojom::blink::NFCMessage::From(pushMessage);
if (!message)
@@ -488,6 +617,12 @@ ScriptPromise NFC::push(ScriptState* scriptState,
return ScriptPromise::rejectWithDOMException(
scriptState, DOMException::create(SyntaxError));
+ if (getNFCMessageSize(message) >
+ device::nfc::mojom::blink::NFCMessage::kMaxSize) {
+ return ScriptPromise::rejectWithDOMException(
+ scriptState, DOMException::create(NotSupportedError));
+ }
+
ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
m_requests.add(resolver);
auto callback = convertToBaseCallback(WTF::bind(&NFC::OnRequestCompleted,
@@ -500,15 +635,11 @@ ScriptPromise NFC::push(ScriptState* scriptState,
return resolver->promise();
}
+// https://w3c.github.io/web-nfc/#dom-nfc-cancelpush
ScriptPromise NFC::cancelPush(ScriptState* scriptState, const String& target) {
- String errorMessage;
- if (!scriptState->getExecutionContext()->isSecureContext(errorMessage))
- return ScriptPromise::rejectWithDOMException(
- scriptState, DOMException::create(SecurityError, errorMessage));
-
- if (!m_nfc)
- return ScriptPromise::rejectWithDOMException(
- scriptState, DOMException::create(NotSupportedError));
+ ScriptPromise promise = rejectIfNotSupported(scriptState);
+ if (!promise.isEmpty())
+ return promise;
ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
m_requests.add(resolver);
@@ -520,24 +651,60 @@ ScriptPromise NFC::cancelPush(ScriptState* scriptState, const String& target) {
return resolver->promise();
}
+// https://w3c.github.io/web-nfc/#watching-for-content
+// https://w3c.github.io/web-nfc/#dom-nfc-watch
ScriptPromise NFC::watch(ScriptState* scriptState,
MessageCallback* callback,
const NFCWatchOptions& options) {
- // TODO(shalamov): To be implemented.
- return ScriptPromise::rejectWithDOMException(
- scriptState, DOMException::create(NotSupportedError));
+ ScriptPromise promise = rejectIfNotSupported(scriptState);
+ if (!promise.isEmpty())
+ return promise;
+
+ ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
+ m_requests.add(resolver);
+ auto watchCallback = convertToBaseCallback(
+ WTF::bind(&NFC::OnWatchRegistered, wrapPersistent(this),
+ wrapPersistent(callback), wrapPersistent(resolver)));
+ m_nfc->Watch(device::nfc::mojom::blink::NFCWatchOptions::From(options),
+ watchCallback);
+ return resolver->promise();
}
+// https://w3c.github.io/web-nfc/#dom-nfc-cancelwatch
ScriptPromise NFC::cancelWatch(ScriptState* scriptState, long id) {
- // TODO(shalamov): To be implemented.
- return ScriptPromise::rejectWithDOMException(
- scriptState, DOMException::create(NotSupportedError));
+ ScriptPromise promise = rejectIfNotSupported(scriptState);
+ if (!promise.isEmpty())
+ return promise;
+
+ if (id) {
+ m_callbacks.remove(id);
+ } else {
+ return ScriptPromise::rejectWithDOMException(
+ scriptState, DOMException::create(NotFoundError));
+ }
+
+ ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
+ m_requests.add(resolver);
+ m_nfc->CancelWatch(id, convertToBaseCallback(WTF::bind(
+ &NFC::OnRequestCompleted, wrapPersistent(this),
+ wrapPersistent(resolver))));
+ return resolver->promise();
}
+// https://w3c.github.io/web-nfc/#dom-nfc-cancelwatch
+// If watchId is not provided to nfc.cancelWatch, cancel all watch operations.
ScriptPromise NFC::cancelWatch(ScriptState* scriptState) {
- // TODO(shalamov): To be implemented.
- return ScriptPromise::rejectWithDOMException(
- scriptState, DOMException::create(NotSupportedError));
+ ScriptPromise promise = rejectIfNotSupported(scriptState);
+ if (!promise.isEmpty())
+ return promise;
+
+ m_callbacks.clear();
+ ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
+ m_requests.add(resolver);
+ m_nfc->CancelAllWatches(convertToBaseCallback(
+ WTF::bind(&NFC::OnRequestCompleted, wrapPersistent(this),
+ wrapPersistent(resolver))));
+ return resolver->promise();
}
void NFC::pageVisibilityChanged() {
@@ -572,26 +739,75 @@ void NFC::OnConnectionError() {
}
m_nfc.reset();
+ m_callbacks.clear();
// If NFCService is not available or disappears when NFC hardware is
// disabled, reject promise with NotSupportedError exception.
- for (ScriptPromiseResolver* resolver : m_requests) {
+ for (ScriptPromiseResolver* resolver : m_requests)
resolver->reject(NFCError::take(
resolver, device::nfc::mojom::blink::NFCErrorType::NOT_SUPPORTED));
- }
m_requests.clear();
}
void NFC::OnWatch(const WTF::Vector<uint32_t>& ids,
- device::nfc::mojom::blink::NFCMessagePtr) {
- // TODO(shalamov): Not implemented.
+ device::nfc::mojom::blink::NFCMessagePtr message) {
+ ScriptState* scriptState =
+ ScriptState::forMainWorld(toLocalFrame(page()->mainFrame()));
haraken 2016/11/22 02:38:14 What happens if OnWatch is called on an isolated w
shalamov 2016/11/22 12:50:41 Unfortunately OnWatch() is a part of mojo client i
haraken 2016/11/22 14:39:09 If an extension uses the nfc object, we need to us
shalamov 2016/11/23 12:10:45 Done.
+ ScriptState::Scope scope(scriptState);
+ NFCMessage nfcMessage = toNFCMessage(message, scriptState);
+
+ for (const auto& id : ids) {
+ auto it = m_callbacks.find(id);
+ if (it != m_callbacks.end())
+ it->value->handleMessage(nfcMessage);
+ }
+}
+
+ScriptPromise NFC::rejectIfNotSupported(ScriptState* scriptState) {
+ String errorMessage;
+ if (!scriptState->getExecutionContext()->isSecureContext(errorMessage)) {
+ return ScriptPromise::rejectWithDOMException(
+ scriptState, DOMException::create(SecurityError, errorMessage));
+ }
+
+ if (!m_nfc) {
+ return ScriptPromise::rejectWithDOMException(
+ scriptState, DOMException::create(NotSupportedError));
+ }
+
+ return ScriptPromise();
+}
+
+void NFC::OnWatchRegistered(MessageCallback* callback,
+ ScriptPromiseResolver* resolver,
+ uint32_t id,
+ device::nfc::mojom::blink::NFCErrorPtr error) {
+ m_requests.remove(resolver);
+
+ // Invalid id was returned.
+ // https://w3c.github.io/web-nfc/#dom-nfc-watch
+ // 8. If the request fails, reject promise with "NotSupportedError"
+ // and abort these steps.
+ if (!id) {
+ resolver->reject(NFCError::take(
+ resolver, device::nfc::mojom::blink::NFCErrorType::NOT_SUPPORTED));
+ return;
+ }
+
+ if (error.is_null()) {
+ m_callbacks.add(id, callback);
+ resolver->resolve(id);
+ } else {
+ resolver->reject(NFCError::take(resolver, error->error_type));
+ }
}
DEFINE_TRACE(NFC) {
PageVisibilityObserver::trace(visitor);
ContextLifecycleObserver::trace(visitor);
visitor->trace(m_requests);
+ visitor->trace(m_callbacks);
}
} // namespace blink
« device/nfc/nfc.mojom ('K') | « third_party/WebKit/Source/modules/nfc/NFC.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698