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

Side by Side Diff: third_party/WebKit/Source/modules/nfc/NFC.cpp

Issue 2885813002: [webnfc] Align nfc.push operation with the specification (Closed)
Patch Set: Rebased to master Created 3 years, 7 months 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 unified diff | Download patch
« no previous file with comments | « third_party/WebKit/Source/modules/nfc/NFC.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "modules/nfc/NFC.h" 5 #include "modules/nfc/NFC.h"
6 6
7 #include "bindings/core/v8/ScriptPromiseResolver.h" 7 #include "bindings/core/v8/ScriptPromiseResolver.h"
8 #include "bindings/core/v8/V8ArrayBuffer.h" 8 #include "bindings/core/v8/V8ArrayBuffer.h"
9 #include "bindings/core/v8/V8StringResource.h" 9 #include "bindings/core/v8/V8StringResource.h"
10 #include "core/dom/DOMArrayBuffer.h" 10 #include "core/dom/DOMArrayBuffer.h"
11 #include "core/dom/DOMException.h" 11 #include "core/dom/DOMException.h"
12 #include "core/dom/Document.h" 12 #include "core/dom/Document.h"
13 #include "core/dom/ExceptionCode.h" 13 #include "core/dom/ExceptionCode.h"
14 #include "core/dom/ExecutionContext.h" 14 #include "core/dom/ExecutionContext.h"
15 #include "core/frame/LocalDOMWindow.h" 15 #include "core/frame/LocalDOMWindow.h"
16 #include "modules/nfc/NFCError.h" 16 #include "modules/nfc/NFCError.h"
17 #include "modules/nfc/NFCMessage.h" 17 #include "modules/nfc/NFCMessage.h"
18 #include "modules/nfc/NFCPushOptions.h" 18 #include "modules/nfc/NFCPushOptions.h"
19 #include "modules/nfc/NFCWatchOptions.h" 19 #include "modules/nfc/NFCWatchOptions.h"
20 #include "platform/mojo/MojoHelper.h" 20 #include "platform/mojo/MojoHelper.h"
21 #include "public/platform/InterfaceProvider.h" 21 #include "public/platform/InterfaceProvider.h"
22 #include "public/platform/Platform.h" 22 #include "public/platform/Platform.h"
23 23
24 namespace { 24 namespace {
25 const char kJsonMimePostfix[] = "+json";
25 const char kJsonMimePrefix[] = "application/"; 26 const char kJsonMimePrefix[] = "application/";
26 const char kJsonMimeType[] = "application/json"; 27 const char kJsonMimeType[] = "application/json";
27 const char kOpaqueMimeType[] = "application/octet-stream"; 28 const char kOpaqueMimeType[] = "application/octet-stream";
28 const char kPlainTextMimeType[] = "text/plain"; 29 const char kPlainTextMimeType[] = "text/plain";
29 const char kPlainTextMimePrefix[] = "text/"; 30 const char kPlainTextMimePrefix[] = "text/";
30 const char kCharSetUTF8[] = ";charset=UTF-8"; 31 const char kCharSetUTF8[] = ";charset=UTF-8";
31 } // anonymous namespace 32 } // anonymous namespace
32 33
33 // Mojo type converters 34 // Mojo type converters
34 namespace mojo { 35 namespace mojo {
35 36
36 using device::mojom::blink::NFCMessage; 37 using device::mojom::blink::NFCMessage;
37 using device::mojom::blink::NFCMessagePtr; 38 using device::mojom::blink::NFCMessagePtr;
38 using device::mojom::blink::NFCRecord; 39 using device::mojom::blink::NFCRecord;
39 using device::mojom::blink::NFCRecordPtr; 40 using device::mojom::blink::NFCRecordPtr;
40 using device::mojom::blink::NFCRecordType; 41 using device::mojom::blink::NFCRecordType;
41 using device::mojom::blink::NFCRecordTypeFilter; 42 using device::mojom::blink::NFCRecordTypeFilter;
42 using device::mojom::blink::NFCPushOptions; 43 using device::mojom::blink::NFCPushOptions;
43 using device::mojom::blink::NFCPushOptionsPtr; 44 using device::mojom::blink::NFCPushOptionsPtr;
44 using device::mojom::blink::NFCPushTarget; 45 using device::mojom::blink::NFCPushTarget;
45 using device::mojom::blink::NFCWatchMode; 46 using device::mojom::blink::NFCWatchMode;
46 using device::mojom::blink::NFCWatchOptions; 47 using device::mojom::blink::NFCWatchOptions;
47 using device::mojom::blink::NFCWatchOptionsPtr; 48 using device::mojom::blink::NFCWatchOptionsPtr;
48 49
49 NFCPushTarget toNFCPushTarget(const WTF::String& target) { 50 NFCPushTarget toNFCPushTarget(const String& target) {
50 if (target == "tag") 51 if (target == "tag")
51 return NFCPushTarget::TAG; 52 return NFCPushTarget::TAG;
52 53
53 if (target == "peer") 54 if (target == "peer")
54 return NFCPushTarget::PEER; 55 return NFCPushTarget::PEER;
55 56
56 return NFCPushTarget::ANY; 57 return NFCPushTarget::ANY;
57 } 58 }
58 59
59 NFCRecordType toNFCRecordType(const WTF::String& recordType) { 60 NFCRecordType toNFCRecordType(const String& recordType) {
60 if (recordType == "empty") 61 if (recordType == "empty")
61 return NFCRecordType::EMPTY; 62 return NFCRecordType::EMPTY;
62 63
63 if (recordType == "text") 64 if (recordType == "text")
64 return NFCRecordType::TEXT; 65 return NFCRecordType::TEXT;
65 66
66 if (recordType == "url") 67 if (recordType == "url")
67 return NFCRecordType::URL; 68 return NFCRecordType::URL;
68 69
69 if (recordType == "json") 70 if (recordType == "json")
70 return NFCRecordType::JSON; 71 return NFCRecordType::JSON;
71 72
72 if (recordType == "opaque") 73 if (recordType == "opaque")
73 return NFCRecordType::OPAQUE_RECORD; 74 return NFCRecordType::OPAQUE_RECORD;
74 75
75 NOTREACHED(); 76 NOTREACHED();
76 return NFCRecordType::EMPTY; 77 return NFCRecordType::EMPTY;
77 } 78 }
78 79
79 NFCWatchMode toNFCWatchMode(const WTF::String& watchMode) { 80 NFCWatchMode toNFCWatchMode(const String& watchMode) {
80 if (watchMode == "web-nfc-only") 81 if (watchMode == "web-nfc-only")
81 return NFCWatchMode::WEBNFC_ONLY; 82 return NFCWatchMode::WEBNFC_ONLY;
82 83
83 if (watchMode == "any") 84 if (watchMode == "any")
84 return NFCWatchMode::ANY; 85 return NFCWatchMode::ANY;
85 86
86 NOTREACHED(); 87 NOTREACHED();
87 return NFCWatchMode::WEBNFC_ONLY; 88 return NFCWatchMode::WEBNFC_ONLY;
88 } 89 }
89 90
(...skipping 17 matching lines...) Expand all
107 108
108 if (value->IsArrayBuffer()) { 109 if (value->IsArrayBuffer()) {
109 return NFCRecordType::OPAQUE_RECORD; 110 return NFCRecordType::OPAQUE_RECORD;
110 } 111 }
111 } 112 }
112 113
113 return NFCRecordType::EMPTY; 114 return NFCRecordType::EMPTY;
114 } 115 }
115 116
116 void setMediaType(NFCRecordPtr& recordPtr, 117 void setMediaType(NFCRecordPtr& recordPtr,
117 const WTF::String& recordMediaType, 118 const String& recordMediaType,
118 const WTF::String& defaultMediaType) { 119 const String& defaultMediaType) {
119 recordPtr->media_type = 120 recordPtr->media_type =
120 recordMediaType.IsEmpty() ? defaultMediaType : recordMediaType; 121 recordMediaType.IsEmpty() ? defaultMediaType : recordMediaType;
121 } 122 }
122 123
123 template <> 124 template <>
124 struct TypeConverter<WTF::Vector<uint8_t>, WTF::String> { 125 struct TypeConverter<Vector<uint8_t>, String> {
125 static WTF::Vector<uint8_t> Convert(const WTF::String& string) { 126 static Vector<uint8_t> Convert(const String& string) {
126 WTF::CString utf8String = string.Utf8(); 127 CString utf8String = string.Utf8();
127 WTF::Vector<uint8_t> array; 128 Vector<uint8_t> array;
128 array.Append(utf8String.data(), utf8String.length()); 129 array.Append(utf8String.data(), utf8String.length());
129 return array; 130 return array;
130 } 131 }
131 }; 132 };
132 133
133 template <> 134 template <>
134 struct TypeConverter<WTF::Vector<uint8_t>, blink::DOMArrayBuffer*> { 135 struct TypeConverter<Vector<uint8_t>, blink::DOMArrayBuffer*> {
135 static WTF::Vector<uint8_t> Convert(blink::DOMArrayBuffer* buffer) { 136 static Vector<uint8_t> Convert(blink::DOMArrayBuffer* buffer) {
136 WTF::Vector<uint8_t> array; 137 Vector<uint8_t> array;
137 array.Append(static_cast<uint8_t*>(buffer->Data()), buffer->ByteLength()); 138 array.Append(static_cast<uint8_t*>(buffer->Data()), buffer->ByteLength());
138 return array; 139 return array;
139 } 140 }
140 }; 141 };
141 142
142 template <> 143 template <>
143 struct TypeConverter<NFCRecordPtr, WTF::String> { 144 struct TypeConverter<NFCRecordPtr, String> {
144 static NFCRecordPtr Convert(const WTF::String& string) { 145 static NFCRecordPtr Convert(const String& string) {
145 NFCRecordPtr record = NFCRecord::New(); 146 NFCRecordPtr record = NFCRecord::New();
146 record->record_type = NFCRecordType::TEXT; 147 record->record_type = NFCRecordType::TEXT;
147 record->media_type = kPlainTextMimeType; 148 record->media_type = kPlainTextMimeType;
148 record->media_type.append(kCharSetUTF8); 149 record->media_type.append(kCharSetUTF8);
149 record->data = mojo::ConvertTo<WTF::Vector<uint8_t>>(string); 150 record->data = mojo::ConvertTo<Vector<uint8_t>>(string);
150 return record; 151 return record;
151 } 152 }
152 }; 153 };
153 154
154 template <> 155 template <>
155 struct TypeConverter<NFCRecordPtr, blink::DOMArrayBuffer*> { 156 struct TypeConverter<NFCRecordPtr, blink::DOMArrayBuffer*> {
156 static NFCRecordPtr Convert(blink::DOMArrayBuffer* buffer) { 157 static NFCRecordPtr Convert(blink::DOMArrayBuffer* buffer) {
157 NFCRecordPtr record = NFCRecord::New(); 158 NFCRecordPtr record = NFCRecord::New();
158 record->record_type = NFCRecordType::OPAQUE_RECORD; 159 record->record_type = NFCRecordType::OPAQUE_RECORD;
159 record->media_type = kOpaqueMimeType; 160 record->media_type = kOpaqueMimeType;
160 record->data = mojo::ConvertTo<WTF::Vector<uint8_t>>(buffer); 161 record->data = mojo::ConvertTo<Vector<uint8_t>>(buffer);
161 return record; 162 return record;
162 } 163 }
163 }; 164 };
164 165
165 template <> 166 template <>
166 struct TypeConverter<NFCMessagePtr, WTF::String> { 167 struct TypeConverter<NFCMessagePtr, String> {
167 static NFCMessagePtr Convert(const WTF::String& string) { 168 static NFCMessagePtr Convert(const String& string) {
168 NFCMessagePtr message = NFCMessage::New(); 169 NFCMessagePtr message = NFCMessage::New();
169 message->data.push_back(NFCRecord::From(string)); 170 message->data.push_back(NFCRecord::From(string));
170 return message; 171 return message;
171 } 172 }
172 }; 173 };
173 174
174 template <> 175 template <>
175 struct TypeConverter<WTF::Optional<WTF::Vector<uint8_t>>, blink::ScriptValue> { 176 struct TypeConverter<Optional<Vector<uint8_t>>, blink::ScriptValue> {
176 static WTF::Optional<WTF::Vector<uint8_t>> Convert( 177 static Optional<Vector<uint8_t>> Convert(
177 const blink::ScriptValue& scriptValue) { 178 const blink::ScriptValue& scriptValue) {
178 v8::Local<v8::Value> value = scriptValue.V8Value(); 179 v8::Local<v8::Value> value = scriptValue.V8Value();
179 180
180 if (value->IsNumber()) 181 if (value->IsNumber()) {
181 return mojo::ConvertTo<WTF::Vector<uint8_t>>( 182 return mojo::ConvertTo<Vector<uint8_t>>(
182 WTF::String::Number(value.As<v8::Number>()->Value())); 183 String::Number(value.As<v8::Number>()->Value()));
184 }
183 185
184 if (value->IsString()) { 186 if (value->IsString()) {
185 blink::V8StringResource<> stringResource = value; 187 blink::V8StringResource<> stringResource = value;
186 if (stringResource.Prepare()) { 188 if (stringResource.Prepare()) {
187 return mojo::ConvertTo<WTF::Vector<uint8_t>>( 189 return mojo::ConvertTo<Vector<uint8_t>>(String(stringResource));
188 WTF::String(stringResource));
189 } 190 }
190 } 191 }
191 192
192 if (value->IsObject() && !value->IsArray() && !value->IsArrayBuffer()) { 193 if (value->IsObject() && !value->IsArray() && !value->IsArrayBuffer()) {
193 v8::Local<v8::String> jsonString; 194 v8::Local<v8::String> jsonString;
194 if (v8::JSON::Stringify(scriptValue.GetContext(), value.As<v8::Object>()) 195 v8::Isolate* isolate = scriptValue.GetIsolate();
195 .ToLocal(&jsonString)) { 196 v8::TryCatch try_catch(isolate);
196 WTF::String wtfString = blink::V8StringToWebCoreString<WTF::String>( 197
197 jsonString, blink::kDoNotExternalize); 198 // https://w3c.github.io/web-nfc/#mapping-json-to-ndef
198 return mojo::ConvertTo<WTF::Vector<uint8_t>>(wtfString); 199 // If serialization throws, reject promise with a "SyntaxError" exception.
200 if (!v8::JSON::Stringify(scriptValue.GetContext(), value.As<v8::Object>())
201 .ToLocal(&jsonString) ||
202 try_catch.HasCaught()) {
203 return WTF::nullopt;
199 } 204 }
205
206 String string = blink::V8StringToWebCoreString<String>(
207 jsonString, blink::kDoNotExternalize);
208 return mojo::ConvertTo<Vector<uint8_t>>(string);
200 } 209 }
201 210
202 if (value->IsArrayBuffer()) 211 if (value->IsArrayBuffer())
203 return mojo::ConvertTo<WTF::Vector<uint8_t>>( 212 return mojo::ConvertTo<Vector<uint8_t>>(
204 blink::V8ArrayBuffer::toImpl(value.As<v8::Object>())); 213 blink::V8ArrayBuffer::toImpl(value.As<v8::Object>()));
205 214
206 return WTF::nullopt; 215 return WTF::nullopt;
207 } 216 }
208 }; 217 };
209 218
210 template <> 219 template <>
211 struct TypeConverter<NFCRecordPtr, blink::NFCRecord> { 220 struct TypeConverter<NFCRecordPtr, blink::NFCRecord> {
212 static NFCRecordPtr Convert(const blink::NFCRecord& record) { 221 static NFCRecordPtr Convert(const blink::NFCRecord& record) {
213 NFCRecordPtr recordPtr = NFCRecord::New(); 222 NFCRecordPtr recordPtr = NFCRecord::New();
(...skipping 18 matching lines...) Expand all
232 setMediaType(recordPtr, record.mediaType(), kJsonMimeType); 241 setMediaType(recordPtr, record.mediaType(), kJsonMimeType);
233 break; 242 break;
234 case NFCRecordType::OPAQUE_RECORD: 243 case NFCRecordType::OPAQUE_RECORD:
235 setMediaType(recordPtr, record.mediaType(), kOpaqueMimeType); 244 setMediaType(recordPtr, record.mediaType(), kOpaqueMimeType);
236 break; 245 break;
237 default: 246 default:
238 NOTREACHED(); 247 NOTREACHED();
239 break; 248 break;
240 } 249 }
241 250
242 auto recordData = 251 auto recordData = mojo::ConvertTo<Optional<Vector<uint8_t>>>(record.data());
243 mojo::ConvertTo<WTF::Optional<WTF::Vector<uint8_t>>>(record.data());
244 // If JS object cannot be converted to uint8_t array, return null, 252 // If JS object cannot be converted to uint8_t array, return null,
245 // interrupt NFCMessage conversion algorithm and reject promise with 253 // interrupt NFCMessage conversion algorithm and reject promise with
246 // SyntaxError exception. 254 // SyntaxError exception.
247 if (!recordData) 255 if (!recordData)
248 return nullptr; 256 return nullptr;
249 257
250 recordPtr->data = recordData.value(); 258 recordPtr->data = recordData.value();
251 return recordPtr; 259 return recordPtr;
252 } 260 }
253 }; 261 };
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 354
347 return watchOptionsPtr; 355 return watchOptionsPtr;
348 } 356 }
349 }; 357 };
350 358
351 } // namespace mojo 359 } // namespace mojo
352 360
353 namespace blink { 361 namespace blink {
354 namespace { 362 namespace {
355 363
356 bool IsValidTextRecord(const NFCRecord& record) { 364 ScriptPromise RejectWithTypeError(ScriptState* script_state,
365 const String& message) {
366 return ScriptPromise::Reject(
367 script_state,
368 V8ThrowException::CreateTypeError(script_state->GetIsolate(), message));
369 }
370
371 ScriptPromise RejectWithDOMException(ScriptState* script_state,
372 ExceptionCode ec,
373 const String& message) {
374 return ScriptPromise::RejectWithDOMException(
375 script_state, DOMException::Create(ec, message));
376 }
377
378 ScriptPromise RejectIfInvalidTextRecord(ScriptState* script_state,
379 const NFCRecord& record) {
357 v8::Local<v8::Value> value = record.data().V8Value(); 380 v8::Local<v8::Value> value = record.data().V8Value();
358 if (!value->IsString() && 381 if (!value->IsString() &&
359 !(value->IsNumber() && !std::isnan(value.As<v8::Number>()->Value()))) 382 !(value->IsNumber() && !std::isnan(value.As<v8::Number>()->Value()))) {
360 return false; 383 return RejectWithTypeError(script_state,
384 "The data for 'text' NFCRecords must be of "
385 "String or UnrestrctedDouble type.");
386 }
361 387
362 if (record.hasMediaType() && 388 if (record.hasMediaType() &&
363 !record.mediaType().StartsWith(kPlainTextMimePrefix, 389 !record.mediaType().StartsWith(kPlainTextMimePrefix,
364 kTextCaseUnicodeInsensitive)) 390 kTextCaseUnicodeInsensitive)) {
365 return false; 391 return RejectWithDOMException(script_state, kSyntaxError,
392 "Invalid media type for 'text' record.");
393 }
366 394
367 return true; 395 return ScriptPromise();
368 } 396 }
369 397
370 bool IsValidURLRecord(const NFCRecord& record) { 398 ScriptPromise RejectIfInvalidURLRecord(ScriptState* script_state,
371 if (!record.data().V8Value()->IsString()) 399 const NFCRecord& record) {
372 return false; 400 if (!record.data().V8Value()->IsString()) {
401 return RejectWithTypeError(
402 script_state, "The data for 'url' NFCRecord must be of String type.");
403 }
373 404
374 blink::V8StringResource<> string_resource = record.data().V8Value(); 405 blink::V8StringResource<> string_resource = record.data().V8Value();
375 if (!string_resource.Prepare()) 406 if (!string_resource.Prepare() || !KURL(KURL(), string_resource).IsValid()) {
376 return false; 407 return RejectWithDOMException(script_state, kSyntaxError,
408 "Cannot parse data for 'url' record.");
409 }
377 410
378 return KURL(KURL(), string_resource).IsValid(); 411 return ScriptPromise();
379 } 412 }
380 413
381 bool IsValidJSONRecord(const NFCRecord& record) { 414 ScriptPromise RejectIfInvalidJSONRecord(ScriptState* script_state,
415 const NFCRecord& record) {
382 v8::Local<v8::Value> value = record.data().V8Value(); 416 v8::Local<v8::Value> value = record.data().V8Value();
383 if (!value->IsObject() || value->IsArrayBuffer()) 417 if (!value->IsObject() || value->IsArrayBuffer()) {
384 return false; 418 return RejectWithTypeError(
419 script_state, "The data for 'json' NFCRecord must be of Object type.");
420 }
385 421
386 if (record.hasMediaType() && !record.mediaType().StartsWith( 422 // If JSON record has media type, it must be equal to "application/json" or
387 kJsonMimePrefix, kTextCaseASCIIInsensitive)) 423 // start with "application/" and end with "+json".
388 return false; 424 if (record.hasMediaType() &&
425 (record.mediaType() != kJsonMimeType &&
426 !(record.mediaType().StartsWith(kJsonMimePrefix,
427 kTextCaseASCIIInsensitive) &&
428 record.mediaType().EndsWith(kJsonMimePostfix,
429 kTextCaseASCIIInsensitive)))) {
430 return RejectWithDOMException(script_state, kSyntaxError,
431 "Invalid media type for 'json' record.");
432 }
389 433
390 return true; 434 return ScriptPromise();
391 } 435 }
392 436
393 bool IsValidOpaqueRecord(const NFCRecord& record) { 437 ScriptPromise RejectIfInvalidOpaqueRecord(ScriptState* script_state,
394 return record.data().V8Value()->IsArrayBuffer(); 438 const NFCRecord& record) {
439 if (!record.data().V8Value()->IsArrayBuffer()) {
440 return RejectWithTypeError(
441 script_state,
442 "The data for 'opaque' NFCRecord must be of ArrayBuffer type.");
443 }
444
445 return ScriptPromise();
395 } 446 }
396 447
397 bool IsValidNFCRecord(const NFCRecord& record) { 448 ScriptPromise RejectIfInvalidNFCRecord(ScriptState* script_state,
449 const NFCRecord& record) {
398 device::mojom::blink::NFCRecordType type; 450 device::mojom::blink::NFCRecordType type;
399 if (record.hasRecordType()) { 451 if (record.hasRecordType()) {
400 type = mojo::toNFCRecordType(record.recordType()); 452 type = mojo::toNFCRecordType(record.recordType());
401 } else { 453 } else {
402 type = mojo::deduceRecordTypeFromDataType(record); 454 type = mojo::deduceRecordTypeFromDataType(record);
403 455
404 // https://w3c.github.io/web-nfc/#creating-web-nfc-message 456 // https://w3c.github.io/web-nfc/#creating-web-nfc-message
405 // If NFCRecord.recordType is not set and record type cannot be deduced 457 // If NFCRecord.recordType is not set and record type cannot be deduced
406 // from NFCRecord.data, reject promise with SyntaxError. 458 // from NFCRecord.data, reject promise with TypeError.
407 if (type == device::mojom::blink::NFCRecordType::EMPTY) 459 if (type == device::mojom::blink::NFCRecordType::EMPTY)
408 return false; 460 return RejectWithTypeError(script_state, "Unknown NFCRecord type.");
409 } 461 }
410 462
411 // Non-empty records must have data. 463 // Non-empty records must have data.
412 if (!record.hasData() && 464 if (!record.hasData() &&
413 (type != device::mojom::blink::NFCRecordType::EMPTY)) { 465 (type != device::mojom::blink::NFCRecordType::EMPTY)) {
414 return false; 466 return RejectWithTypeError(script_state,
467 "Nonempty NFCRecord must have data.");
415 } 468 }
416 469
417 switch (type) { 470 switch (type) {
418 case device::mojom::blink::NFCRecordType::TEXT: 471 case device::mojom::blink::NFCRecordType::TEXT:
419 return IsValidTextRecord(record); 472 return RejectIfInvalidTextRecord(script_state, record);
420 case device::mojom::blink::NFCRecordType::URL: 473 case device::mojom::blink::NFCRecordType::URL:
421 return IsValidURLRecord(record); 474 return RejectIfInvalidURLRecord(script_state, record);
422 case device::mojom::blink::NFCRecordType::JSON: 475 case device::mojom::blink::NFCRecordType::JSON:
423 return IsValidJSONRecord(record); 476 return RejectIfInvalidJSONRecord(script_state, record);
424 case device::mojom::blink::NFCRecordType::OPAQUE_RECORD: 477 case device::mojom::blink::NFCRecordType::OPAQUE_RECORD:
425 return IsValidOpaqueRecord(record); 478 return RejectIfInvalidOpaqueRecord(script_state, record);
426 case device::mojom::blink::NFCRecordType::EMPTY: 479 case device::mojom::blink::NFCRecordType::EMPTY:
427 return !record.hasData() && record.mediaType().IsEmpty(); 480 return ScriptPromise();
428 } 481 }
429 482
430 NOTREACHED(); 483 NOTREACHED();
431 return false; 484 return RejectWithTypeError(script_state,
485 "Invalid NFCRecordType was provided.");
432 } 486 }
433 487
434 bool IsValidNFCRecordArray(const HeapVector<NFCRecord>& records) { 488 ScriptPromise RejectIfInvalidNFCRecordArray(
435 if (records.IsEmpty()) 489 ScriptState* script_state,
436 return false; 490 const HeapVector<NFCRecord>& records) {
437
438 for (const auto& record : records) { 491 for (const auto& record : records) {
439 if (!IsValidNFCRecord(record)) 492 ScriptPromise isValidRecord =
440 return false; 493 RejectIfInvalidNFCRecord(script_state, record);
494 if (!isValidRecord.IsEmpty())
495 return isValidRecord;
441 } 496 }
442 497
443 return true; 498 return ScriptPromise();
444 } 499 }
445 500
446 bool IsValidNFCPushMessage(const NFCPushMessage& message) { 501 ScriptPromise RejectIfInvalidNFCPushMessage(
502 ScriptState* script_state,
503 const NFCPushMessage& push_message) {
447 // If NFCPushMessage of invalid type, reject promise with TypeError 504 // If NFCPushMessage of invalid type, reject promise with TypeError
448 if (!message.isNFCMessage() && !message.isString() && 505 if (!push_message.isNFCMessage() && !push_message.isString() &&
449 !message.isArrayBuffer()) 506 !push_message.isArrayBuffer()) {
450 return false; 507 return RejectWithTypeError(script_state,
508 "Invalid NFCPushMessage type was provided.");
509 }
451 510
452 if (message.isNFCMessage()) { 511 if (push_message.isNFCMessage()) {
453 // https://w3c.github.io/web-nfc/#the-push-method 512 // https://w3c.github.io/web-nfc/#the-push-method
454 // If NFCMessage.data is empty, reject promise with TypeError 513 // If NFCMessage.data is empty, reject promise with TypeError
455 if (!message.getAsNFCMessage().hasData()) 514 const NFCMessage& message = push_message.getAsNFCMessage();
456 return false; 515 if (!message.hasData() || message.data().IsEmpty()) {
516 return RejectWithTypeError(script_state,
517 "Empty NFCMessage was provided.");
518 }
457 519
458 return IsValidNFCRecordArray(message.getAsNFCMessage().data()); 520 return RejectIfInvalidNFCRecordArray(script_state, message.data());
459 } 521 }
460 522
461 return true; 523 return ScriptPromise();
462 } 524 }
463 525
464 bool SetURL(const String& origin, 526 bool SetURL(const String& origin,
465 device::mojom::blink::NFCMessagePtr& message) { 527 device::mojom::blink::NFCMessagePtr& message) {
466 KURL origin_url(kParsedURLString, origin); 528 KURL origin_url(kParsedURLString, origin);
467 529
468 if (!message->url.IsEmpty() && origin_url.CanSetPathname()) { 530 if (!message->url.IsEmpty() && origin_url.CanSetPathname()) {
469 origin_url.SetPath(message->url); 531 origin_url.SetPath(message->url);
470 } 532 }
471 533
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
610 672
611 // https://w3c.github.io/web-nfc/#writing-or-pushing-content 673 // https://w3c.github.io/web-nfc/#writing-or-pushing-content
612 // https://w3c.github.io/web-nfc/#dom-nfc-push 674 // https://w3c.github.io/web-nfc/#dom-nfc-push
613 ScriptPromise NFC::push(ScriptState* script_state, 675 ScriptPromise NFC::push(ScriptState* script_state,
614 const NFCPushMessage& push_message, 676 const NFCPushMessage& push_message,
615 const NFCPushOptions& options) { 677 const NFCPushOptions& options) {
616 ScriptPromise promise = RejectIfNotSupported(script_state); 678 ScriptPromise promise = RejectIfNotSupported(script_state);
617 if (!promise.IsEmpty()) 679 if (!promise.IsEmpty())
618 return promise; 680 return promise;
619 681
620 if (!IsValidNFCPushMessage(push_message)) { 682 ScriptPromise isValidMessage =
621 return ScriptPromise::Reject( 683 RejectIfInvalidNFCPushMessage(script_state, push_message);
622 script_state, V8ThrowException::CreateTypeError( 684 if (!isValidMessage.IsEmpty())
623 script_state->GetIsolate(), 685 return isValidMessage;
624 "Invalid NFCPushMessage type was provided."));
625 }
626 686
627 // https://w3c.github.io/web-nfc/#dom-nfc-push 687 // https://w3c.github.io/web-nfc/#dom-nfc-push
628 // 9. If timeout value is NaN or negative, reject promise with "TypeError" 688 // 9. If timeout value is NaN or negative, reject promise with "TypeError"
629 // and abort these steps. 689 // and abort these steps.
630 if (options.hasTimeout() && 690 if (options.hasTimeout() &&
631 (std::isnan(options.timeout()) || options.timeout() < 0)) { 691 (std::isnan(options.timeout()) || options.timeout() < 0)) {
632 return ScriptPromise::Reject( 692 return RejectWithTypeError(
633 script_state, 693 script_state, "Invalid NFCPushOptions.timeout value was provided.");
634 V8ThrowException::CreateTypeError(
635 script_state->GetIsolate(),
636 "Invalid NFCPushOptions.timeout value was provided."));
637 } 694 }
638 695
639 device::mojom::blink::NFCMessagePtr message = 696 device::mojom::blink::NFCMessagePtr message =
640 device::mojom::blink::NFCMessage::From(push_message); 697 device::mojom::blink::NFCMessage::From(push_message);
641 if (!message) 698 if (!message) {
642 return ScriptPromise::RejectWithDOMException( 699 return RejectWithDOMException(script_state, kSyntaxError,
643 script_state, DOMException::Create(kSyntaxError)); 700 "Cannot convert NFCMessage.");
701 }
644 702
645 if (!SetURL( 703 if (!SetURL(
646 ExecutionContext::From(script_state)->GetSecurityOrigin()->ToString(), 704 ExecutionContext::From(script_state)->GetSecurityOrigin()->ToString(),
647 message)) 705 message)) {
648 return ScriptPromise::RejectWithDOMException( 706 return RejectWithDOMException(script_state, kSyntaxError,
649 script_state, DOMException::Create(kSyntaxError)); 707 "Cannot set WebNFC Id.");
708 }
650 709
651 if (GetNFCMessageSize(message) > device::mojom::blink::NFCMessage::kMaxSize) { 710 if (GetNFCMessageSize(message) > device::mojom::blink::NFCMessage::kMaxSize) {
652 return ScriptPromise::RejectWithDOMException( 711 return RejectWithDOMException(script_state, kNotSupportedError,
653 script_state, DOMException::Create(kNotSupportedError)); 712 "NFCMessage exceeds maximum supported size.");
654 } 713 }
655 714
656 ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); 715 ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
657 requests_.insert(resolver); 716 requests_.insert(resolver);
658 auto callback = ConvertToBaseCallback(WTF::Bind(&NFC::OnRequestCompleted, 717 auto callback = ConvertToBaseCallback(WTF::Bind(&NFC::OnRequestCompleted,
659 WrapPersistent(this), 718 WrapPersistent(this),
660 WrapPersistent(resolver))); 719 WrapPersistent(resolver)));
661 nfc_->Push(std::move(message), 720 nfc_->Push(std::move(message),
662 device::mojom::blink::NFCPushOptions::From(options), callback); 721 device::mojom::blink::NFCPushOptions::From(options), callback);
663 722
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
702 761
703 // https://w3c.github.io/web-nfc/#dom-nfc-cancelwatch 762 // https://w3c.github.io/web-nfc/#dom-nfc-cancelwatch
704 ScriptPromise NFC::cancelWatch(ScriptState* script_state, long id) { 763 ScriptPromise NFC::cancelWatch(ScriptState* script_state, long id) {
705 ScriptPromise promise = RejectIfNotSupported(script_state); 764 ScriptPromise promise = RejectIfNotSupported(script_state);
706 if (!promise.IsEmpty()) 765 if (!promise.IsEmpty())
707 return promise; 766 return promise;
708 767
709 if (id) { 768 if (id) {
710 callbacks_.erase(id); 769 callbacks_.erase(id);
711 } else { 770 } else {
712 return ScriptPromise::RejectWithDOMException( 771 return RejectWithDOMException(script_state, kNotFoundError,
713 script_state, DOMException::Create(kNotFoundError)); 772 "Provided watch id cannot be found.");
714 } 773 }
715 774
716 ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); 775 ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
717 requests_.insert(resolver); 776 requests_.insert(resolver);
718 nfc_->CancelWatch(id, ConvertToBaseCallback(WTF::Bind( 777 nfc_->CancelWatch(id, ConvertToBaseCallback(WTF::Bind(
719 &NFC::OnRequestCompleted, WrapPersistent(this), 778 &NFC::OnRequestCompleted, WrapPersistent(this),
720 WrapPersistent(resolver)))); 779 WrapPersistent(resolver))));
721 return resolver->Promise(); 780 return resolver->Promise();
722 } 781 }
723 782
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
761 else 820 else
762 resolver->Reject(NFCError::Take(resolver, error->error_type)); 821 resolver->Reject(NFCError::Take(resolver, error->error_type));
763 } 822 }
764 823
765 void NFC::OnConnectionError() { 824 void NFC::OnConnectionError() {
766 nfc_.reset(); 825 nfc_.reset();
767 callbacks_.clear(); 826 callbacks_.clear();
768 827
769 // If NFCService is not available or disappears when NFC hardware is 828 // If NFCService is not available or disappears when NFC hardware is
770 // disabled, reject promise with NotSupportedError exception. 829 // disabled, reject promise with NotSupportedError exception.
771 for (ScriptPromiseResolver* resolver : requests_) { 830 for (ScriptPromiseResolver* resolver : requests_)
772 resolver->Reject(NFCError::Take( 831 resolver->Reject(NFCError::Take(
773 resolver, device::mojom::blink::NFCErrorType::NOT_SUPPORTED)); 832 resolver, device::mojom::blink::NFCErrorType::NOT_SUPPORTED));
774 }
775 833
776 requests_.clear(); 834 requests_.clear();
777 } 835 }
778 836
779 void NFC::OnWatch(const WTF::Vector<uint32_t>& ids, 837 void NFC::OnWatch(const Vector<uint32_t>& ids,
780 device::mojom::blink::NFCMessagePtr message) { 838 device::mojom::blink::NFCMessagePtr message) {
781 for (const auto& id : ids) { 839 for (const auto& id : ids) {
782 auto it = callbacks_.find(id); 840 auto it = callbacks_.find(id);
783 if (it != callbacks_.end()) { 841 if (it != callbacks_.end()) {
784 MessageCallback* callback = it->value; 842 MessageCallback* callback = it->value;
785 ScriptState* script_state = callback->GetScriptState(); 843 ScriptState* script_state = callback->GetScriptState();
786 DCHECK(script_state); 844 DCHECK(script_state);
787 ScriptState::Scope scope(script_state); 845 ScriptState::Scope scope(script_state);
788 NFCMessage nfc_message = ToNFCMessage(script_state, message); 846 NFCMessage nfc_message = ToNFCMessage(script_state, message);
789 callback->handleMessage(nfc_message); 847 callback->handleMessage(nfc_message);
(...skipping 15 matching lines...) Expand all
805 return false; 863 return false;
806 } 864 }
807 865
808 return true; 866 return true;
809 } 867 }
810 868
811 ScriptPromise NFC::RejectIfNotSupported(ScriptState* script_state) { 869 ScriptPromise NFC::RejectIfNotSupported(ScriptState* script_state) {
812 String error_message; 870 String error_message;
813 if (!IsSupportedInContext(ExecutionContext::From(script_state), 871 if (!IsSupportedInContext(ExecutionContext::From(script_state),
814 error_message)) { 872 error_message)) {
815 return ScriptPromise::RejectWithDOMException( 873 return RejectWithDOMException(script_state, kSecurityError, error_message);
816 script_state, DOMException::Create(kSecurityError, error_message));
817 } 874 }
818 875
819 if (!nfc_) { 876 if (!nfc_) {
820 return ScriptPromise::RejectWithDOMException( 877 return RejectWithDOMException(script_state, kNotSupportedError,
821 script_state, DOMException::Create(kNotSupportedError)); 878 "WebNFC is not supported.");
822 } 879 }
823 880
824 return ScriptPromise(); 881 return ScriptPromise();
825 } 882 }
826 883
827 void NFC::OnWatchRegistered(MessageCallback* callback, 884 void NFC::OnWatchRegistered(MessageCallback* callback,
828 ScriptPromiseResolver* resolver, 885 ScriptPromiseResolver* resolver,
829 uint32_t id, 886 uint32_t id,
830 device::mojom::blink::NFCErrorPtr error) { 887 device::mojom::blink::NFCErrorPtr error) {
831 requests_.erase(resolver); 888 requests_.erase(resolver);
(...skipping 17 matching lines...) Expand all
849 } 906 }
850 907
851 DEFINE_TRACE(NFC) { 908 DEFINE_TRACE(NFC) {
852 PageVisibilityObserver::Trace(visitor); 909 PageVisibilityObserver::Trace(visitor);
853 ContextLifecycleObserver::Trace(visitor); 910 ContextLifecycleObserver::Trace(visitor);
854 visitor->Trace(requests_); 911 visitor->Trace(requests_);
855 visitor->Trace(callbacks_); 912 visitor->Trace(callbacks_);
856 } 913 }
857 914
858 } // namespace blink 915 } // namespace blink
OLDNEW
« no previous file with comments | « 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