OLD | NEW |
---|---|
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/frame/LocalDOMWindow.h" | 14 #include "core/frame/LocalDOMWindow.h" |
15 #include "modules/nfc/NFCError.h" | 15 #include "modules/nfc/NFCError.h" |
16 #include "modules/nfc/NFCMessage.h" | 16 #include "modules/nfc/NFCMessage.h" |
17 #include "modules/nfc/NFCPushOptions.h" | 17 #include "modules/nfc/NFCPushOptions.h" |
18 #include "modules/nfc/NFCWatchOptions.h" | |
18 #include "platform/mojo/MojoHelper.h" | 19 #include "platform/mojo/MojoHelper.h" |
19 #include "public/platform/InterfaceProvider.h" | 20 #include "public/platform/InterfaceProvider.h" |
20 #include "public/platform/Platform.h" | 21 #include "public/platform/Platform.h" |
21 | 22 |
22 namespace { | 23 namespace { |
23 const char kJsonMimePrefix[] = "application/"; | 24 const char kJsonMimePrefix[] = "application/"; |
24 const char kJsonMimeType[] = "application/json"; | 25 const char kJsonMimeType[] = "application/json"; |
25 const char kOpaqueMimeType[] = "application/octet-stream"; | 26 const char kOpaqueMimeType[] = "application/octet-stream"; |
26 const char kPlainTextMimeType[] = "text/plain"; | 27 const char kPlainTextMimeType[] = "text/plain"; |
27 const char kPlainTextMimePrefix[] = "text/"; | 28 const char kPlainTextMimePrefix[] = "text/"; |
28 const char kCharSetUTF8[] = ";charset=UTF-8"; | 29 const char kCharSetUTF8[] = ";charset=UTF-8"; |
29 } // anonymous namespace | 30 } // anonymous namespace |
30 | 31 |
31 // Mojo type converters | 32 // Mojo type converters |
32 namespace mojo { | 33 namespace mojo { |
33 | 34 |
34 using device::nfc::mojom::blink::NFCMessage; | 35 using device::nfc::mojom::blink::NFCMessage; |
35 using device::nfc::mojom::blink::NFCMessagePtr; | 36 using device::nfc::mojom::blink::NFCMessagePtr; |
36 using device::nfc::mojom::blink::NFCRecord; | 37 using device::nfc::mojom::blink::NFCRecord; |
37 using device::nfc::mojom::blink::NFCRecordPtr; | 38 using device::nfc::mojom::blink::NFCRecordPtr; |
38 using device::nfc::mojom::blink::NFCRecordType; | 39 using device::nfc::mojom::blink::NFCRecordType; |
40 using device::nfc::mojom::blink::NFCRecordTypeFilter; | |
39 using device::nfc::mojom::blink::NFCPushOptions; | 41 using device::nfc::mojom::blink::NFCPushOptions; |
40 using device::nfc::mojom::blink::NFCPushOptionsPtr; | 42 using device::nfc::mojom::blink::NFCPushOptionsPtr; |
41 using device::nfc::mojom::blink::NFCPushTarget; | 43 using device::nfc::mojom::blink::NFCPushTarget; |
44 using device::nfc::mojom::blink::NFCWatchMode; | |
45 using device::nfc::mojom::blink::NFCWatchOptions; | |
46 using device::nfc::mojom::blink::NFCWatchOptionsPtr; | |
42 | 47 |
43 NFCPushTarget toNFCPushTarget(const WTF::String& target) { | 48 NFCPushTarget toNFCPushTarget(const WTF::String& target) { |
44 if (target == "tag") | 49 if (target == "tag") |
45 return NFCPushTarget::TAG; | 50 return NFCPushTarget::TAG; |
46 | 51 |
47 if (target == "peer") | 52 if (target == "peer") |
48 return NFCPushTarget::PEER; | 53 return NFCPushTarget::PEER; |
49 | 54 |
50 return NFCPushTarget::ANY; | 55 return NFCPushTarget::ANY; |
51 } | 56 } |
(...skipping 11 matching lines...) Expand all Loading... | |
63 if (recordType == "json") | 68 if (recordType == "json") |
64 return NFCRecordType::JSON; | 69 return NFCRecordType::JSON; |
65 | 70 |
66 if (recordType == "opaque") | 71 if (recordType == "opaque") |
67 return NFCRecordType::OPAQUE_RECORD; | 72 return NFCRecordType::OPAQUE_RECORD; |
68 | 73 |
69 NOTREACHED(); | 74 NOTREACHED(); |
70 return NFCRecordType::EMPTY; | 75 return NFCRecordType::EMPTY; |
71 } | 76 } |
72 | 77 |
78 NFCWatchMode toNFCWatchMode(const WTF::String& watchMode) { | |
79 if (watchMode == "web-nfc-only") | |
80 return NFCWatchMode::WEBNFC_ONLY; | |
81 | |
82 if (watchMode == "any") | |
83 return NFCWatchMode::ANY; | |
84 | |
85 NOTREACHED(); | |
86 return NFCWatchMode::WEBNFC_ONLY; | |
87 } | |
88 | |
73 // https://w3c.github.io/web-nfc/#creating-web-nfc-message Step 2.1 | 89 // https://w3c.github.io/web-nfc/#creating-web-nfc-message Step 2.1 |
74 // If NFCRecord type is not provided, deduce NFCRecord type from JS data type: | 90 // If NFCRecord type is not provided, deduce NFCRecord type from JS data type: |
75 // String or Number => 'text' record | 91 // String or Number => 'text' record |
76 // ArrayBuffer => 'opaque' record | 92 // ArrayBuffer => 'opaque' record |
77 // JSON serializable Object => 'json' record | 93 // JSON serializable Object => 'json' record |
78 NFCRecordType deduceRecordTypeFromDataType(const blink::NFCRecord& record) { | 94 NFCRecordType deduceRecordTypeFromDataType(const blink::NFCRecord& record) { |
79 if (record.hasData()) { | 95 if (record.hasData()) { |
80 v8::Local<v8::Value> value = record.data().v8Value(); | 96 v8::Local<v8::Value> value = record.data().v8Value(); |
81 | 97 |
82 if (value->IsString() || | 98 if (value->IsString() || |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
295 | 311 |
296 if (pushOptions.hasIgnoreRead()) | 312 if (pushOptions.hasIgnoreRead()) |
297 pushOptionsPtr->ignore_read = pushOptions.ignoreRead(); | 313 pushOptionsPtr->ignore_read = pushOptions.ignoreRead(); |
298 else | 314 else |
299 pushOptionsPtr->ignore_read = true; | 315 pushOptionsPtr->ignore_read = true; |
300 | 316 |
301 return pushOptionsPtr; | 317 return pushOptionsPtr; |
302 } | 318 } |
303 }; | 319 }; |
304 | 320 |
321 template <> | |
322 struct TypeConverter<NFCWatchOptionsPtr, blink::NFCWatchOptions> { | |
323 static NFCWatchOptionsPtr Convert( | |
324 const blink::NFCWatchOptions& watchOptions) { | |
325 // https://w3c.github.io/web-nfc/#the-nfcwatchoptions-dictionary | |
326 // Default values for NFCWatchOptions dictionary are: | |
327 // url = "", recordType = null, mediaType = "", mode = "web-nfc-only" | |
328 NFCWatchOptionsPtr watchOptionsPtr = NFCWatchOptions::New(); | |
329 watchOptionsPtr->url = watchOptions.url(); | |
330 watchOptionsPtr->media_type = watchOptions.mediaType(); | |
331 | |
332 if (watchOptions.hasMode()) | |
333 watchOptionsPtr->mode = toNFCWatchMode(watchOptions.mode()); | |
334 else | |
335 watchOptionsPtr->mode = NFCWatchMode::WEBNFC_ONLY; | |
336 | |
337 if (watchOptions.hasRecordType()) { | |
338 watchOptionsPtr->record_filter = NFCRecordTypeFilter::New(); | |
339 watchOptionsPtr->record_filter->record_type = | |
340 toNFCRecordType(watchOptions.recordType()); | |
341 } | |
342 | |
343 return watchOptionsPtr; | |
344 } | |
345 }; | |
346 | |
305 } // namespace mojo | 347 } // namespace mojo |
306 | 348 |
307 namespace blink { | 349 namespace blink { |
308 namespace { | 350 namespace { |
309 | 351 |
310 bool isValidTextRecord(const NFCRecord& record) { | 352 bool isValidTextRecord(const NFCRecord& record) { |
311 v8::Local<v8::Value> value = record.data().v8Value(); | 353 v8::Local<v8::Value> value = record.data().v8Value(); |
312 if (!value->IsString() && | 354 if (!value->IsString() && |
313 !(value->IsNumber() && !std::isnan(value.As<v8::Number>()->Value()))) | 355 !(value->IsNumber() && !std::isnan(value.As<v8::Number>()->Value()))) |
314 return false; | 356 return false; |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
419 KURL originURL(ParsedURLString, origin); | 461 KURL originURL(ParsedURLString, origin); |
420 | 462 |
421 if (!message->url.isEmpty() && originURL.canSetPathname()) { | 463 if (!message->url.isEmpty() && originURL.canSetPathname()) { |
422 originURL.setPath(message->url); | 464 originURL.setPath(message->url); |
423 } | 465 } |
424 | 466 |
425 message->url = originURL; | 467 message->url = originURL; |
426 return originURL.isValid(); | 468 return originURL.isValid(); |
427 } | 469 } |
428 | 470 |
471 String toNFCRecordType(const device::nfc::mojom::blink::NFCRecordType& type) { | |
472 switch (type) { | |
473 case device::nfc::mojom::blink::NFCRecordType::TEXT: | |
474 return "text"; | |
475 case device::nfc::mojom::blink::NFCRecordType::URL: | |
476 return "url"; | |
477 case device::nfc::mojom::blink::NFCRecordType::JSON: | |
478 return "json"; | |
479 case device::nfc::mojom::blink::NFCRecordType::OPAQUE_RECORD: | |
480 return "opaque"; | |
481 case device::nfc::mojom::blink::NFCRecordType::EMPTY: | |
482 return "empty"; | |
483 } | |
484 | |
485 NOTREACHED(); | |
486 return String(); | |
487 } | |
488 | |
489 v8::Local<v8::Value> toV8(const device::nfc::mojom::blink::NFCRecordPtr& record, | |
490 ScriptState* scriptState) { | |
491 switch (record->record_type) { | |
492 case device::nfc::mojom::blink::NFCRecordType::TEXT: | |
493 case device::nfc::mojom::blink::NFCRecordType::URL: | |
494 case device::nfc::mojom::blink::NFCRecordType::JSON: { | |
495 String stringData; | |
496 if (!record->data.isEmpty()) { | |
497 stringData = String::fromUTF8WithLatin1Fallback( | |
498 static_cast<unsigned char*>(&record->data.first()), | |
499 record->data.size()); | |
500 } | |
501 | |
502 if (record->record_type == | |
503 device::nfc::mojom::blink::NFCRecordType::JSON) { | |
504 return v8::JSON::Parse(scriptState->isolate(), | |
505 v8String(scriptState->isolate(), stringData)) | |
506 .ToLocalChecked(); | |
507 } | |
508 | |
509 return v8String(scriptState->isolate(), stringData); | |
510 } | |
511 | |
512 case device::nfc::mojom::blink::NFCRecordType::OPAQUE_RECORD: { | |
513 if (!record->data.isEmpty()) { | |
514 DOMArrayBuffer* buffer = DOMArrayBuffer::create( | |
515 static_cast<void*>(&record->data.first()), record->data.size()); | |
516 return toV8(buffer, scriptState->context()->Global(), | |
517 scriptState->isolate()); | |
518 } | |
519 | |
520 return v8::Null(scriptState->isolate()); | |
521 } | |
522 | |
523 case device::nfc::mojom::blink::NFCRecordType::EMPTY: | |
524 return v8::Null(scriptState->isolate()); | |
525 } | |
526 | |
527 NOTREACHED(); | |
528 return v8::Local<v8::Value>(); | |
529 } | |
530 | |
531 NFCRecord toNFCRecord(const device::nfc::mojom::blink::NFCRecordPtr& record, | |
532 ScriptState* scriptState) { | |
533 NFCRecord nfcRecord; | |
534 nfcRecord.setMediaType(record->media_type); | |
535 nfcRecord.setRecordType(toNFCRecordType(record->record_type)); | |
536 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
| |
537 return nfcRecord; | |
538 } | |
539 | |
540 NFCMessage toNFCMessage(const device::nfc::mojom::blink::NFCMessagePtr& message, | |
541 ScriptState* scriptState) { | |
542 NFCMessage nfcMessage; | |
543 nfcMessage.setURL(message->url); | |
544 blink::HeapVector<NFCRecord> records; | |
545 for (size_t i = 0; i < message->data.size(); ++i) | |
546 records.append(toNFCRecord(message->data[i], scriptState)); | |
547 nfcMessage.setData(records); | |
548 return nfcMessage; | |
549 } | |
550 | |
551 size_t getNFCMessageSize( | |
552 const device::nfc::mojom::blink::NFCMessagePtr& message) { | |
553 size_t messageSize = message->url.charactersSizeInBytes(); | |
554 for (size_t i = 0; i < message->data.size(); ++i) { | |
555 messageSize += message->data[i]->media_type.charactersSizeInBytes(); | |
556 messageSize += message->data[i]->data.size(); | |
557 } | |
558 return messageSize; | |
559 } | |
560 | |
429 } // anonymous namespace | 561 } // anonymous namespace |
430 | 562 |
431 NFC::NFC(LocalFrame* frame) | 563 NFC::NFC(LocalFrame* frame) |
432 : PageVisibilityObserver(frame->page()), | 564 : PageVisibilityObserver(frame->page()), |
433 ContextLifecycleObserver(frame->document()), | 565 ContextLifecycleObserver(frame->document()), |
434 m_client(this) { | 566 m_client(this) { |
435 ThreadState::current()->registerPreFinalizer(this); | 567 ThreadState::current()->registerPreFinalizer(this); |
436 frame->interfaceProvider()->getInterface(mojo::GetProxy(&m_nfc)); | 568 frame->interfaceProvider()->getInterface(mojo::GetProxy(&m_nfc)); |
437 m_nfc.set_connection_error_handler(convertToBaseCallback( | 569 m_nfc.set_connection_error_handler(convertToBaseCallback( |
438 WTF::bind(&NFC::OnConnectionError, wrapWeakPersistent(this)))); | 570 WTF::bind(&NFC::OnConnectionError, wrapWeakPersistent(this)))); |
(...skipping 11 matching lines...) Expand all Loading... | |
450 DCHECK(m_requests.isEmpty()); | 582 DCHECK(m_requests.isEmpty()); |
451 } | 583 } |
452 | 584 |
453 void NFC::dispose() { | 585 void NFC::dispose() { |
454 m_client.Close(); | 586 m_client.Close(); |
455 } | 587 } |
456 | 588 |
457 void NFC::contextDestroyed() { | 589 void NFC::contextDestroyed() { |
458 m_nfc.reset(); | 590 m_nfc.reset(); |
459 m_requests.clear(); | 591 m_requests.clear(); |
592 m_callbacks.clear(); | |
460 } | 593 } |
461 | 594 |
462 // https://w3c.github.io/web-nfc/#writing-or-pushing-content | 595 // https://w3c.github.io/web-nfc/#writing-or-pushing-content |
596 // https://w3c.github.io/web-nfc/#dom-nfc-push | |
463 ScriptPromise NFC::push(ScriptState* scriptState, | 597 ScriptPromise NFC::push(ScriptState* scriptState, |
464 const NFCPushMessage& pushMessage, | 598 const NFCPushMessage& pushMessage, |
465 const NFCPushOptions& options) { | 599 const NFCPushOptions& options) { |
466 String errorMessage; | 600 ScriptPromise promise = rejectIfNotSupported(scriptState); |
467 if (!scriptState->getExecutionContext()->isSecureContext(errorMessage)) | 601 if (!promise.isEmpty()) |
468 return ScriptPromise::rejectWithDOMException( | 602 return promise; |
469 scriptState, DOMException::create(SecurityError, errorMessage)); | |
470 | 603 |
471 DOMException* exception = isValidNFCPushMessage(pushMessage); | 604 DOMException* exception = isValidNFCPushMessage(pushMessage); |
472 if (exception) | 605 if (exception) |
473 return ScriptPromise::rejectWithDOMException(scriptState, exception); | 606 return ScriptPromise::rejectWithDOMException(scriptState, exception); |
474 | 607 |
475 if (!m_nfc) | |
476 return ScriptPromise::rejectWithDOMException( | |
477 scriptState, DOMException::create(NotSupportedError)); | |
478 | |
479 device::nfc::mojom::blink::NFCMessagePtr message = | 608 device::nfc::mojom::blink::NFCMessagePtr message = |
480 device::nfc::mojom::blink::NFCMessage::From(pushMessage); | 609 device::nfc::mojom::blink::NFCMessage::From(pushMessage); |
481 if (!message) | 610 if (!message) |
482 return ScriptPromise::rejectWithDOMException( | 611 return ScriptPromise::rejectWithDOMException( |
483 scriptState, DOMException::create(SyntaxError)); | 612 scriptState, DOMException::create(SyntaxError)); |
484 | 613 |
485 if (!setURL( | 614 if (!setURL( |
486 scriptState->getExecutionContext()->getSecurityOrigin()->toString(), | 615 scriptState->getExecutionContext()->getSecurityOrigin()->toString(), |
487 message)) | 616 message)) |
488 return ScriptPromise::rejectWithDOMException( | 617 return ScriptPromise::rejectWithDOMException( |
489 scriptState, DOMException::create(SyntaxError)); | 618 scriptState, DOMException::create(SyntaxError)); |
490 | 619 |
620 if (getNFCMessageSize(message) > | |
621 device::nfc::mojom::blink::NFCMessage::kMaxSize) { | |
622 return ScriptPromise::rejectWithDOMException( | |
623 scriptState, DOMException::create(NotSupportedError)); | |
624 } | |
625 | |
491 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); | 626 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); |
492 m_requests.add(resolver); | 627 m_requests.add(resolver); |
493 auto callback = convertToBaseCallback(WTF::bind(&NFC::OnRequestCompleted, | 628 auto callback = convertToBaseCallback(WTF::bind(&NFC::OnRequestCompleted, |
494 wrapPersistent(this), | 629 wrapPersistent(this), |
495 wrapPersistent(resolver))); | 630 wrapPersistent(resolver))); |
496 m_nfc->Push(std::move(message), | 631 m_nfc->Push(std::move(message), |
497 device::nfc::mojom::blink::NFCPushOptions::From(options), | 632 device::nfc::mojom::blink::NFCPushOptions::From(options), |
498 callback); | 633 callback); |
499 | 634 |
500 return resolver->promise(); | 635 return resolver->promise(); |
501 } | 636 } |
502 | 637 |
638 // https://w3c.github.io/web-nfc/#dom-nfc-cancelpush | |
503 ScriptPromise NFC::cancelPush(ScriptState* scriptState, const String& target) { | 639 ScriptPromise NFC::cancelPush(ScriptState* scriptState, const String& target) { |
504 String errorMessage; | 640 ScriptPromise promise = rejectIfNotSupported(scriptState); |
505 if (!scriptState->getExecutionContext()->isSecureContext(errorMessage)) | 641 if (!promise.isEmpty()) |
506 return ScriptPromise::rejectWithDOMException( | 642 return promise; |
507 scriptState, DOMException::create(SecurityError, errorMessage)); | |
508 | |
509 if (!m_nfc) | |
510 return ScriptPromise::rejectWithDOMException( | |
511 scriptState, DOMException::create(NotSupportedError)); | |
512 | 643 |
513 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); | 644 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); |
514 m_requests.add(resolver); | 645 m_requests.add(resolver); |
515 auto callback = convertToBaseCallback(WTF::bind(&NFC::OnRequestCompleted, | 646 auto callback = convertToBaseCallback(WTF::bind(&NFC::OnRequestCompleted, |
516 wrapPersistent(this), | 647 wrapPersistent(this), |
517 wrapPersistent(resolver))); | 648 wrapPersistent(resolver))); |
518 m_nfc->CancelPush(mojo::toNFCPushTarget(target), callback); | 649 m_nfc->CancelPush(mojo::toNFCPushTarget(target), callback); |
519 | 650 |
520 return resolver->promise(); | 651 return resolver->promise(); |
521 } | 652 } |
522 | 653 |
654 // https://w3c.github.io/web-nfc/#watching-for-content | |
655 // https://w3c.github.io/web-nfc/#dom-nfc-watch | |
523 ScriptPromise NFC::watch(ScriptState* scriptState, | 656 ScriptPromise NFC::watch(ScriptState* scriptState, |
524 MessageCallback* callback, | 657 MessageCallback* callback, |
525 const NFCWatchOptions& options) { | 658 const NFCWatchOptions& options) { |
526 // TODO(shalamov): To be implemented. | 659 ScriptPromise promise = rejectIfNotSupported(scriptState); |
527 return ScriptPromise::rejectWithDOMException( | 660 if (!promise.isEmpty()) |
528 scriptState, DOMException::create(NotSupportedError)); | 661 return promise; |
662 | |
663 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); | |
664 m_requests.add(resolver); | |
665 auto watchCallback = convertToBaseCallback( | |
666 WTF::bind(&NFC::OnWatchRegistered, wrapPersistent(this), | |
667 wrapPersistent(callback), wrapPersistent(resolver))); | |
668 m_nfc->Watch(device::nfc::mojom::blink::NFCWatchOptions::From(options), | |
669 watchCallback); | |
670 return resolver->promise(); | |
529 } | 671 } |
530 | 672 |
673 // https://w3c.github.io/web-nfc/#dom-nfc-cancelwatch | |
531 ScriptPromise NFC::cancelWatch(ScriptState* scriptState, long id) { | 674 ScriptPromise NFC::cancelWatch(ScriptState* scriptState, long id) { |
532 // TODO(shalamov): To be implemented. | 675 ScriptPromise promise = rejectIfNotSupported(scriptState); |
533 return ScriptPromise::rejectWithDOMException( | 676 if (!promise.isEmpty()) |
534 scriptState, DOMException::create(NotSupportedError)); | 677 return promise; |
678 | |
679 if (id) { | |
680 m_callbacks.remove(id); | |
681 } else { | |
682 return ScriptPromise::rejectWithDOMException( | |
683 scriptState, DOMException::create(NotFoundError)); | |
684 } | |
685 | |
686 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); | |
687 m_requests.add(resolver); | |
688 m_nfc->CancelWatch(id, convertToBaseCallback(WTF::bind( | |
689 &NFC::OnRequestCompleted, wrapPersistent(this), | |
690 wrapPersistent(resolver)))); | |
691 return resolver->promise(); | |
535 } | 692 } |
536 | 693 |
694 // https://w3c.github.io/web-nfc/#dom-nfc-cancelwatch | |
695 // If watchId is not provided to nfc.cancelWatch, cancel all watch operations. | |
537 ScriptPromise NFC::cancelWatch(ScriptState* scriptState) { | 696 ScriptPromise NFC::cancelWatch(ScriptState* scriptState) { |
538 // TODO(shalamov): To be implemented. | 697 ScriptPromise promise = rejectIfNotSupported(scriptState); |
539 return ScriptPromise::rejectWithDOMException( | 698 if (!promise.isEmpty()) |
540 scriptState, DOMException::create(NotSupportedError)); | 699 return promise; |
700 | |
701 m_callbacks.clear(); | |
702 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); | |
703 m_requests.add(resolver); | |
704 m_nfc->CancelAllWatches(convertToBaseCallback( | |
705 WTF::bind(&NFC::OnRequestCompleted, wrapPersistent(this), | |
706 wrapPersistent(resolver)))); | |
707 return resolver->promise(); | |
541 } | 708 } |
542 | 709 |
543 void NFC::pageVisibilityChanged() { | 710 void NFC::pageVisibilityChanged() { |
544 // If service is not initialized, there cannot be any pending NFC activities | 711 // If service is not initialized, there cannot be any pending NFC activities |
545 if (!m_nfc) | 712 if (!m_nfc) |
546 return; | 713 return; |
547 | 714 |
548 // NFC operations should be suspended. | 715 // NFC operations should be suspended. |
549 // https://w3c.github.io/web-nfc/#nfc-suspended | 716 // https://w3c.github.io/web-nfc/#nfc-suspended |
550 if (page()->visibilityState() == PageVisibilityStateVisible) | 717 if (page()->visibilityState() == PageVisibilityStateVisible) |
(...skipping 14 matching lines...) Expand all Loading... | |
565 resolver->reject(NFCError::take(resolver, error->error_type)); | 732 resolver->reject(NFCError::take(resolver, error->error_type)); |
566 } | 733 } |
567 | 734 |
568 void NFC::OnConnectionError() { | 735 void NFC::OnConnectionError() { |
569 if (!Platform::current()) { | 736 if (!Platform::current()) { |
570 // TODO(rockot): Clean this up once renderer shutdown sequence is fixed. | 737 // TODO(rockot): Clean this up once renderer shutdown sequence is fixed. |
571 return; | 738 return; |
572 } | 739 } |
573 | 740 |
574 m_nfc.reset(); | 741 m_nfc.reset(); |
742 m_callbacks.clear(); | |
575 | 743 |
576 // If NFCService is not available or disappears when NFC hardware is | 744 // If NFCService is not available or disappears when NFC hardware is |
577 // disabled, reject promise with NotSupportedError exception. | 745 // disabled, reject promise with NotSupportedError exception. |
578 for (ScriptPromiseResolver* resolver : m_requests) { | 746 for (ScriptPromiseResolver* resolver : m_requests) |
579 resolver->reject(NFCError::take( | 747 resolver->reject(NFCError::take( |
580 resolver, device::nfc::mojom::blink::NFCErrorType::NOT_SUPPORTED)); | 748 resolver, device::nfc::mojom::blink::NFCErrorType::NOT_SUPPORTED)); |
581 } | |
582 | 749 |
583 m_requests.clear(); | 750 m_requests.clear(); |
584 } | 751 } |
585 | 752 |
586 void NFC::OnWatch(const WTF::Vector<uint32_t>& ids, | 753 void NFC::OnWatch(const WTF::Vector<uint32_t>& ids, |
587 device::nfc::mojom::blink::NFCMessagePtr) { | 754 device::nfc::mojom::blink::NFCMessagePtr message) { |
588 // TODO(shalamov): Not implemented. | 755 ScriptState* scriptState = |
756 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.
| |
757 ScriptState::Scope scope(scriptState); | |
758 NFCMessage nfcMessage = toNFCMessage(message, scriptState); | |
759 | |
760 for (const auto& id : ids) { | |
761 auto it = m_callbacks.find(id); | |
762 if (it != m_callbacks.end()) | |
763 it->value->handleMessage(nfcMessage); | |
764 } | |
765 } | |
766 | |
767 ScriptPromise NFC::rejectIfNotSupported(ScriptState* scriptState) { | |
768 String errorMessage; | |
769 if (!scriptState->getExecutionContext()->isSecureContext(errorMessage)) { | |
770 return ScriptPromise::rejectWithDOMException( | |
771 scriptState, DOMException::create(SecurityError, errorMessage)); | |
772 } | |
773 | |
774 if (!m_nfc) { | |
775 return ScriptPromise::rejectWithDOMException( | |
776 scriptState, DOMException::create(NotSupportedError)); | |
777 } | |
778 | |
779 return ScriptPromise(); | |
780 } | |
781 | |
782 void NFC::OnWatchRegistered(MessageCallback* callback, | |
783 ScriptPromiseResolver* resolver, | |
784 uint32_t id, | |
785 device::nfc::mojom::blink::NFCErrorPtr error) { | |
786 m_requests.remove(resolver); | |
787 | |
788 // Invalid id was returned. | |
789 // https://w3c.github.io/web-nfc/#dom-nfc-watch | |
790 // 8. If the request fails, reject promise with "NotSupportedError" | |
791 // and abort these steps. | |
792 if (!id) { | |
793 resolver->reject(NFCError::take( | |
794 resolver, device::nfc::mojom::blink::NFCErrorType::NOT_SUPPORTED)); | |
795 return; | |
796 } | |
797 | |
798 if (error.is_null()) { | |
799 m_callbacks.add(id, callback); | |
800 resolver->resolve(id); | |
801 } else { | |
802 resolver->reject(NFCError::take(resolver, error->error_type)); | |
803 } | |
589 } | 804 } |
590 | 805 |
591 DEFINE_TRACE(NFC) { | 806 DEFINE_TRACE(NFC) { |
592 PageVisibilityObserver::trace(visitor); | 807 PageVisibilityObserver::trace(visitor); |
593 ContextLifecycleObserver::trace(visitor); | 808 ContextLifecycleObserver::trace(visitor); |
594 visitor->trace(m_requests); | 809 visitor->trace(m_requests); |
810 visitor->trace(m_callbacks); | |
595 } | 811 } |
596 | 812 |
597 } // namespace blink | 813 } // namespace blink |
OLD | NEW |