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

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: Removed 'the' articles 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::nfc::mojom::blink::NFCMessage; 37 using device::nfc::mojom::blink::NFCMessage;
37 using device::nfc::mojom::blink::NFCMessagePtr; 38 using device::nfc::mojom::blink::NFCMessagePtr;
38 using device::nfc::mojom::blink::NFCRecord; 39 using device::nfc::mojom::blink::NFCRecord;
39 using device::nfc::mojom::blink::NFCRecordPtr; 40 using device::nfc::mojom::blink::NFCRecordPtr;
40 using device::nfc::mojom::blink::NFCRecordType; 41 using device::nfc::mojom::blink::NFCRecordType;
41 using device::nfc::mojom::blink::NFCRecordTypeFilter; 42 using device::nfc::mojom::blink::NFCRecordTypeFilter;
42 using device::nfc::mojom::blink::NFCPushOptions; 43 using device::nfc::mojom::blink::NFCPushOptions;
43 using device::nfc::mojom::blink::NFCPushOptionsPtr; 44 using device::nfc::mojom::blink::NFCPushOptionsPtr;
44 using device::nfc::mojom::blink::NFCPushTarget; 45 using device::nfc::mojom::blink::NFCPushTarget;
45 using device::nfc::mojom::blink::NFCWatchMode; 46 using device::nfc::mojom::blink::NFCWatchMode;
46 using device::nfc::mojom::blink::NFCWatchOptions; 47 using device::nfc::mojom::blink::NFCWatchOptions;
47 using device::nfc::mojom::blink::NFCWatchOptionsPtr; 48 using device::nfc::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::nfc::mojom::blink::NFCRecordType type; 450 device::nfc::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::nfc::mojom::blink::NFCRecordType::EMPTY) 459 if (type == device::nfc::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::nfc::mojom::blink::NFCRecordType::EMPTY)) { 465 (type != device::nfc::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::nfc::mojom::blink::NFCRecordType::TEXT: 471 case device::nfc::mojom::blink::NFCRecordType::TEXT:
419 return IsValidTextRecord(record); 472 return RejectIfInvalidTextRecord(script_state, record);
420 case device::nfc::mojom::blink::NFCRecordType::URL: 473 case device::nfc::mojom::blink::NFCRecordType::URL:
421 return IsValidURLRecord(record); 474 return RejectIfInvalidURLRecord(script_state, record);
422 case device::nfc::mojom::blink::NFCRecordType::JSON: 475 case device::nfc::mojom::blink::NFCRecordType::JSON:
423 return IsValidJSONRecord(record); 476 return RejectIfInvalidJSONRecord(script_state, record);
424 case device::nfc::mojom::blink::NFCRecordType::OPAQUE_RECORD: 477 case device::nfc::mojom::blink::NFCRecordType::OPAQUE_RECORD:
425 return IsValidOpaqueRecord(record); 478 return RejectIfInvalidOpaqueRecord(script_state, record);
426 case device::nfc::mojom::blink::NFCRecordType::EMPTY: 479 case device::nfc::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::nfc::mojom::blink::NFCMessagePtr& message) { 527 device::nfc::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 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
614 676
615 // https://w3c.github.io/web-nfc/#writing-or-pushing-content 677 // https://w3c.github.io/web-nfc/#writing-or-pushing-content
616 // https://w3c.github.io/web-nfc/#dom-nfc-push 678 // https://w3c.github.io/web-nfc/#dom-nfc-push
617 ScriptPromise NFC::push(ScriptState* script_state, 679 ScriptPromise NFC::push(ScriptState* script_state,
618 const NFCPushMessage& push_message, 680 const NFCPushMessage& push_message,
619 const NFCPushOptions& options) { 681 const NFCPushOptions& options) {
620 ScriptPromise promise = RejectIfNotSupported(script_state); 682 ScriptPromise promise = RejectIfNotSupported(script_state);
621 if (!promise.IsEmpty()) 683 if (!promise.IsEmpty())
622 return promise; 684 return promise;
623 685
624 if (!IsValidNFCPushMessage(push_message)) { 686 ScriptPromise isValidMessage =
625 return ScriptPromise::Reject( 687 RejectIfInvalidNFCPushMessage(script_state, push_message);
626 script_state, V8ThrowException::CreateTypeError( 688 if (!isValidMessage.IsEmpty())
627 script_state->GetIsolate(), 689 return isValidMessage;
628 "Invalid NFCPushMessage type was provided."));
629 }
630 690
631 // https://w3c.github.io/web-nfc/#dom-nfc-push 691 // https://w3c.github.io/web-nfc/#dom-nfc-push
632 // 9. If timeout value is NaN or negative, reject promise with "TypeError" 692 // 9. If timeout value is NaN or negative, reject promise with "TypeError"
633 // and abort these steps. 693 // and abort these steps.
634 if (options.hasTimeout() && 694 if (options.hasTimeout() &&
635 (std::isnan(options.timeout()) || options.timeout() < 0)) { 695 (std::isnan(options.timeout()) || options.timeout() < 0)) {
636 return ScriptPromise::Reject( 696 return RejectWithTypeError(
637 script_state, 697 script_state, "Invalid NFCPushOptions.timeout value was provided.");
638 V8ThrowException::CreateTypeError(
639 script_state->GetIsolate(),
640 "Invalid NFCPushOptions.timeout value was provided."));
641 } 698 }
642 699
643 device::nfc::mojom::blink::NFCMessagePtr message = 700 device::nfc::mojom::blink::NFCMessagePtr message =
644 device::nfc::mojom::blink::NFCMessage::From(push_message); 701 device::nfc::mojom::blink::NFCMessage::From(push_message);
645 if (!message) 702 if (!message) {
646 return ScriptPromise::RejectWithDOMException( 703 return RejectWithDOMException(script_state, kSyntaxError,
647 script_state, DOMException::Create(kSyntaxError)); 704 "Cannot convert NFCMessage.");
705 }
648 706
649 if (!SetURL( 707 if (!SetURL(
650 ExecutionContext::From(script_state)->GetSecurityOrigin()->ToString(), 708 ExecutionContext::From(script_state)->GetSecurityOrigin()->ToString(),
651 message)) 709 message)) {
652 return ScriptPromise::RejectWithDOMException( 710 return RejectWithDOMException(script_state, kSyntaxError,
653 script_state, DOMException::Create(kSyntaxError)); 711 "Cannot set WebNFC Id.");
712 }
654 713
655 if (GetNFCMessageSize(message) > 714 if (GetNFCMessageSize(message) >
656 device::nfc::mojom::blink::NFCMessage::kMaxSize) { 715 device::nfc::mojom::blink::NFCMessage::kMaxSize) {
657 return ScriptPromise::RejectWithDOMException( 716 return RejectWithDOMException(script_state, kNotSupportedError,
658 script_state, DOMException::Create(kNotSupportedError)); 717 "NFCMessage exceeds maximum supported size.");
659 } 718 }
660 719
661 ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); 720 ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
662 requests_.insert(resolver); 721 requests_.insert(resolver);
663 auto callback = ConvertToBaseCallback(WTF::Bind(&NFC::OnRequestCompleted, 722 auto callback = ConvertToBaseCallback(WTF::Bind(&NFC::OnRequestCompleted,
664 WrapPersistent(this), 723 WrapPersistent(this),
665 WrapPersistent(resolver))); 724 WrapPersistent(resolver)));
666 nfc_->Push(std::move(message), 725 nfc_->Push(std::move(message),
667 device::nfc::mojom::blink::NFCPushOptions::From(options), 726 device::nfc::mojom::blink::NFCPushOptions::From(options),
668 callback); 727 callback);
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
708 767
709 // https://w3c.github.io/web-nfc/#dom-nfc-cancelwatch 768 // https://w3c.github.io/web-nfc/#dom-nfc-cancelwatch
710 ScriptPromise NFC::cancelWatch(ScriptState* script_state, long id) { 769 ScriptPromise NFC::cancelWatch(ScriptState* script_state, long id) {
711 ScriptPromise promise = RejectIfNotSupported(script_state); 770 ScriptPromise promise = RejectIfNotSupported(script_state);
712 if (!promise.IsEmpty()) 771 if (!promise.IsEmpty())
713 return promise; 772 return promise;
714 773
715 if (id) { 774 if (id) {
716 callbacks_.erase(id); 775 callbacks_.erase(id);
717 } else { 776 } else {
718 return ScriptPromise::RejectWithDOMException( 777 return RejectWithDOMException(script_state, kNotFoundError,
719 script_state, DOMException::Create(kNotFoundError)); 778 "Provided watch id cannot be found.");
720 } 779 }
721 780
722 ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); 781 ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
723 requests_.insert(resolver); 782 requests_.insert(resolver);
724 nfc_->CancelWatch(id, ConvertToBaseCallback(WTF::Bind( 783 nfc_->CancelWatch(id, ConvertToBaseCallback(WTF::Bind(
725 &NFC::OnRequestCompleted, WrapPersistent(this), 784 &NFC::OnRequestCompleted, WrapPersistent(this),
726 WrapPersistent(resolver)))); 785 WrapPersistent(resolver))));
727 return resolver->Promise(); 786 return resolver->Promise();
728 } 787 }
729 788
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
774 833
775 // If NFCService is not available or disappears when NFC hardware is 834 // If NFCService is not available or disappears when NFC hardware is
776 // disabled, reject promise with NotSupportedError exception. 835 // disabled, reject promise with NotSupportedError exception.
777 for (ScriptPromiseResolver* resolver : requests_) 836 for (ScriptPromiseResolver* resolver : requests_)
778 resolver->Reject(NFCError::Take( 837 resolver->Reject(NFCError::Take(
779 resolver, device::nfc::mojom::blink::NFCErrorType::NOT_SUPPORTED)); 838 resolver, device::nfc::mojom::blink::NFCErrorType::NOT_SUPPORTED));
780 839
781 requests_.clear(); 840 requests_.clear();
782 } 841 }
783 842
784 void NFC::OnWatch(const WTF::Vector<uint32_t>& ids, 843 void NFC::OnWatch(const Vector<uint32_t>& ids,
785 device::nfc::mojom::blink::NFCMessagePtr message) { 844 device::nfc::mojom::blink::NFCMessagePtr message) {
786 for (const auto& id : ids) { 845 for (const auto& id : ids) {
787 auto it = callbacks_.find(id); 846 auto it = callbacks_.find(id);
788 if (it != callbacks_.end()) { 847 if (it != callbacks_.end()) {
789 MessageCallback* callback = it->value; 848 MessageCallback* callback = it->value;
790 ScriptState* script_state = callback->GetScriptState(); 849 ScriptState* script_state = callback->GetScriptState();
791 DCHECK(script_state); 850 DCHECK(script_state);
792 ScriptState::Scope scope(script_state); 851 ScriptState::Scope scope(script_state);
793 NFCMessage nfc_message = ToNFCMessage(script_state, message); 852 NFCMessage nfc_message = ToNFCMessage(script_state, message);
794 callback->handleMessage(nfc_message); 853 callback->handleMessage(nfc_message);
(...skipping 15 matching lines...) Expand all
810 return false; 869 return false;
811 } 870 }
812 871
813 return true; 872 return true;
814 } 873 }
815 874
816 ScriptPromise NFC::RejectIfNotSupported(ScriptState* script_state) { 875 ScriptPromise NFC::RejectIfNotSupported(ScriptState* script_state) {
817 String error_message; 876 String error_message;
818 if (!IsSupportedInContext(ExecutionContext::From(script_state), 877 if (!IsSupportedInContext(ExecutionContext::From(script_state),
819 error_message)) { 878 error_message)) {
820 return ScriptPromise::RejectWithDOMException( 879 return RejectWithDOMException(script_state, kSecurityError, error_message);
821 script_state, DOMException::Create(kSecurityError, error_message));
822 } 880 }
823 881
824 if (!nfc_) { 882 if (!nfc_) {
825 return ScriptPromise::RejectWithDOMException( 883 return RejectWithDOMException(script_state, kNotSupportedError,
826 script_state, DOMException::Create(kNotSupportedError)); 884 "WebNFC is not supported.");
827 } 885 }
828 886
829 return ScriptPromise(); 887 return ScriptPromise();
830 } 888 }
831 889
832 void NFC::OnWatchRegistered(MessageCallback* callback, 890 void NFC::OnWatchRegistered(MessageCallback* callback,
833 ScriptPromiseResolver* resolver, 891 ScriptPromiseResolver* resolver,
834 uint32_t id, 892 uint32_t id,
835 device::nfc::mojom::blink::NFCErrorPtr error) { 893 device::nfc::mojom::blink::NFCErrorPtr error) {
836 requests_.erase(resolver); 894 requests_.erase(resolver);
(...skipping 17 matching lines...) Expand all
854 } 912 }
855 913
856 DEFINE_TRACE(NFC) { 914 DEFINE_TRACE(NFC) {
857 PageVisibilityObserver::Trace(visitor); 915 PageVisibilityObserver::Trace(visitor);
858 ContextLifecycleObserver::Trace(visitor); 916 ContextLifecycleObserver::Trace(visitor);
859 visitor->Trace(requests_); 917 visitor->Trace(requests_);
860 visitor->Trace(callbacks_); 918 visitor->Trace(callbacks_);
861 } 919 }
862 920
863 } // namespace blink 921 } // 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