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/JSONValuesForV8.h" | 7 #include "bindings/core/v8/JSONValuesForV8.h" |
8 #include "bindings/core/v8/ScriptPromiseResolver.h" | 8 #include "bindings/core/v8/ScriptPromiseResolver.h" |
9 #include "bindings/core/v8/V8ArrayBuffer.h" | 9 #include "bindings/core/v8/V8ArrayBuffer.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/ExceptionCode.h" | 12 #include "core/dom/ExceptionCode.h" |
13 #include "core/frame/LocalDOMWindow.h" | 13 #include "core/frame/LocalDOMWindow.h" |
14 #include "modules/nfc/NFCError.h" | 14 #include "modules/nfc/NFCError.h" |
15 #include "modules/nfc/NFCMessage.h" | 15 #include "modules/nfc/NFCMessage.h" |
16 #include "modules/nfc/NFCPushOptions.h" | 16 #include "modules/nfc/NFCPushOptions.h" |
| 17 #include "modules/nfc/NFCWatchOptions.h" |
17 #include "platform/mojo/MojoHelper.h" | 18 #include "platform/mojo/MojoHelper.h" |
18 #include "public/platform/ServiceRegistry.h" | 19 #include "public/platform/ServiceRegistry.h" |
19 | 20 |
20 namespace { | 21 namespace { |
21 const char kJsonMimePrefix[] = "application/"; | 22 const char kJsonMimePrefix[] = "application/"; |
22 const char kJsonMimeType[] = "application/json"; | 23 const char kJsonMimeType[] = "application/json"; |
23 const char kOpaqueMimeType[] = "application/octet-stream"; | 24 const char kOpaqueMimeType[] = "application/octet-stream"; |
24 const char kPlainTextMimeType[] = "text/plain"; | 25 const char kPlainTextMimeType[] = "text/plain"; |
25 const char kPlainTextMimePrefix[] = "text/"; | 26 const char kPlainTextMimePrefix[] = "text/"; |
26 const char kCharSetUTF8[] = ";charset=UTF-8"; | 27 const char kCharSetUTF8[] = ";charset=UTF-8"; |
27 } // anonymous namespace | 28 } // anonymous namespace |
28 | 29 |
29 // Mojo type converters | 30 // Mojo type converters |
30 namespace mojo { | 31 namespace mojo { |
31 | 32 |
32 using device::wtf::NFCMessage; | 33 using device::wtf::NFCMessage; |
33 using device::wtf::NFCMessagePtr; | 34 using device::wtf::NFCMessagePtr; |
34 using device::wtf::NFCRecord; | 35 using device::wtf::NFCRecord; |
35 using device::wtf::NFCRecordPtr; | 36 using device::wtf::NFCRecordPtr; |
36 using device::wtf::NFCRecordType; | 37 using device::wtf::NFCRecordType; |
| 38 using device::wtf::NFCRecordTypeFilter; |
| 39 using device::wtf::NFCRecordTypeFilterPtr; |
37 using device::wtf::NFCPushOptions; | 40 using device::wtf::NFCPushOptions; |
38 using device::wtf::NFCPushOptionsPtr; | 41 using device::wtf::NFCPushOptionsPtr; |
39 using device::wtf::NFCPushTarget; | 42 using device::wtf::NFCPushTarget; |
| 43 using device::wtf::NFCWatchMode; |
| 44 using device::wtf::NFCWatchOptions; |
| 45 using device::wtf::NFCWatchOptionsPtr; |
40 | 46 |
41 NFCPushTarget toNFCPushTarget(const WTF::String& target) | 47 NFCPushTarget toNFCPushTarget(const WTF::String& target) |
42 { | 48 { |
43 if (target == "tag") | 49 if (target == "tag") |
44 return NFCPushTarget::TAG; | 50 return NFCPushTarget::TAG; |
45 | 51 |
46 if (target == "peer") | 52 if (target == "peer") |
47 return NFCPushTarget::PEER; | 53 return NFCPushTarget::PEER; |
48 | 54 |
49 return NFCPushTarget::ANY; | 55 return NFCPushTarget::ANY; |
(...skipping 13 matching lines...) Expand all Loading... |
63 if (recordType == "json") | 69 if (recordType == "json") |
64 return NFCRecordType::JSON; | 70 return NFCRecordType::JSON; |
65 | 71 |
66 if (recordType == "opaque") | 72 if (recordType == "opaque") |
67 return NFCRecordType::OPAQUE_RECORD; | 73 return NFCRecordType::OPAQUE_RECORD; |
68 | 74 |
69 ASSERT_NOT_REACHED(); | 75 ASSERT_NOT_REACHED(); |
70 return NFCRecordType::EMPTY; | 76 return NFCRecordType::EMPTY; |
71 } | 77 } |
72 | 78 |
| 79 NFCWatchMode toNFCWatchMode(const WTF::String& watchMode) |
| 80 { |
| 81 if (watchMode == "web-nfc-only") |
| 82 return NFCWatchMode::WEBNFC_ONLY; |
| 83 |
| 84 if (watchMode == "any") |
| 85 return NFCWatchMode::ANY; |
| 86 |
| 87 ASSERT_NOT_REACHED(); |
| 88 return NFCWatchMode::WEBNFC_ONLY; |
| 89 } |
| 90 |
73 // https://w3c.github.io/web-nfc/#creating-web-nfc-message Step 2.1 | 91 // https://w3c.github.io/web-nfc/#creating-web-nfc-message Step 2.1 |
74 // If NFCRecord type is not provided, deduct NFCRecord type from JS data type: | 92 // If NFCRecord type is not provided, deduct NFCRecord type from JS data type: |
75 // String or Number => 'text' record | 93 // String or Number => 'text' record |
76 // ArrayBuffer => 'opaque' record | 94 // ArrayBuffer => 'opaque' record |
77 // JSON serializable Object => 'json' record | 95 // JSON serializable Object => 'json' record |
78 NFCRecordType deductRecordTypeFromDataType(const blink::NFCRecord& record) | 96 NFCRecordType deductRecordTypeFromDataType(const blink::NFCRecord& record) |
79 { | 97 { |
80 if (record.hasData()) { | 98 if (record.hasData()) { |
81 v8::Local<v8::Value> value = record.data().v8Value(); | 99 v8::Local<v8::Value> value = record.data().v8Value(); |
82 | 100 |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
301 | 319 |
302 if (pushOptions.hasIgnoreRead()) | 320 if (pushOptions.hasIgnoreRead()) |
303 pushOptionsPtr->ignoreRead = pushOptions.ignoreRead(); | 321 pushOptionsPtr->ignoreRead = pushOptions.ignoreRead(); |
304 else | 322 else |
305 pushOptionsPtr->ignoreRead = true; | 323 pushOptionsPtr->ignoreRead = true; |
306 | 324 |
307 return pushOptionsPtr; | 325 return pushOptionsPtr; |
308 } | 326 } |
309 }; | 327 }; |
310 | 328 |
| 329 template <> |
| 330 struct TypeConverter<NFCWatchOptionsPtr, blink::NFCWatchOptions> { |
| 331 static NFCWatchOptionsPtr Convert(const blink::NFCWatchOptions& watchOptions
) |
| 332 { |
| 333 // https://w3c.github.io/web-nfc/#the-nfcwatchoptions-dictionary |
| 334 // Default values for NFCWatchOptions dictionary are: |
| 335 // url = "", recordType = null, mediaType = "", mode = "web-nfc-only" |
| 336 NFCWatchOptionsPtr watchOptionsPtr = NFCWatchOptions::New(); |
| 337 watchOptionsPtr->url = watchOptions.url(); |
| 338 watchOptionsPtr->mediaType = watchOptions.mediaType(); |
| 339 |
| 340 if (watchOptions.hasMode()) |
| 341 watchOptionsPtr->mode = toNFCWatchMode(watchOptions.mode()); |
| 342 else |
| 343 watchOptionsPtr->mode = NFCWatchMode::WEBNFC_ONLY; |
| 344 |
| 345 if (watchOptions.hasRecordType()) { |
| 346 watchOptionsPtr->recordFilter = NFCRecordTypeFilter::New(); |
| 347 watchOptionsPtr->recordFilter->recordType = toNFCRecordType(watchOpt
ions.recordType()); |
| 348 } |
| 349 |
| 350 return watchOptionsPtr; |
| 351 } |
| 352 }; |
| 353 |
311 } // namespace mojo | 354 } // namespace mojo |
312 | 355 |
313 namespace blink { | 356 namespace blink { |
314 | 357 |
315 | 358 |
316 namespace { | 359 namespace { |
317 | 360 |
318 bool isValidTextRecord(const NFCRecord& record) | 361 bool isValidTextRecord(const NFCRecord& record) |
319 { | 362 { |
320 v8::Local<v8::Value> value = record.data().v8Value(); | 363 v8::Local<v8::Value> value = record.data().v8Value(); |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
423 KURL originURL(ParsedURLString, origin); | 466 KURL originURL(ParsedURLString, origin); |
424 | 467 |
425 if (!message->url.isEmpty() && originURL.canSetPathname()) { | 468 if (!message->url.isEmpty() && originURL.canSetPathname()) { |
426 originURL.setPath(message->url); | 469 originURL.setPath(message->url); |
427 } | 470 } |
428 | 471 |
429 message->url = originURL; | 472 message->url = originURL; |
430 return originURL.isValid(); | 473 return originURL.isValid(); |
431 } | 474 } |
432 | 475 |
| 476 String toNFCRecordType(const device::wtf::NFCRecordType& type) |
| 477 { |
| 478 switch (type) { |
| 479 case device::wtf::NFCRecordType::TEXT: |
| 480 return "text"; |
| 481 case device::wtf::NFCRecordType::URL: |
| 482 return "url"; |
| 483 case device::wtf::NFCRecordType::JSON: |
| 484 return "json"; |
| 485 case device::wtf::NFCRecordType::OPAQUE_RECORD: |
| 486 return "opaque"; |
| 487 case device::wtf::NFCRecordType::EMPTY: |
| 488 return "empty"; |
| 489 } |
| 490 |
| 491 ASSERT_NOT_REACHED(); |
| 492 return String(); |
| 493 } |
| 494 |
| 495 v8::Local<v8::Value> toV8(const device::wtf::NFCRecordPtr& record, ScriptState*
scriptState) |
| 496 { |
| 497 switch (record->recordType) { |
| 498 case device::wtf::NFCRecordType::TEXT: |
| 499 case device::wtf::NFCRecordType::URL: |
| 500 case device::wtf::NFCRecordType::JSON: { |
| 501 String stringData; |
| 502 if (!record->data.empty()) |
| 503 stringData = String::fromUTF8WithLatin1Fallback(static_cast<unsigned
char*>(&record->data.front()), record->data.size()); |
| 504 |
| 505 if (record->recordType == device::wtf::NFCRecordType::JSON) |
| 506 return v8::JSON::Parse(scriptState->isolate(), v8String(scriptState-
>isolate(), stringData)).ToLocalChecked(); |
| 507 return v8String(scriptState->isolate(), stringData); |
| 508 } |
| 509 |
| 510 case device::wtf::NFCRecordType::OPAQUE_RECORD: { |
| 511 if (!record->data.empty()) { |
| 512 DOMArrayBuffer* buffer = DOMArrayBuffer::create(static_cast<void*>(&
record->data.front()), record->data.size()); |
| 513 return toV8(buffer, scriptState->context()->Global(), scriptState->i
solate()); |
| 514 } |
| 515 |
| 516 return v8::Null(scriptState->isolate()); |
| 517 } |
| 518 |
| 519 case device::wtf::NFCRecordType::EMPTY: |
| 520 return v8::Null(scriptState->isolate()); |
| 521 } |
| 522 |
| 523 ASSERT_NOT_REACHED(); |
| 524 return v8::Local<v8::Value>(); |
| 525 } |
| 526 |
| 527 NFCRecord toNFCRecord(const device::wtf::NFCRecordPtr& record, ScriptState* scri
ptState) |
| 528 { |
| 529 NFCRecord nfcRecord; |
| 530 nfcRecord.setMediaType(record->mediaType); |
| 531 nfcRecord.setRecordType(toNFCRecordType(record->recordType)); |
| 532 nfcRecord.setData(ScriptValue(scriptState, toV8(record, scriptState))); |
| 533 return nfcRecord; |
| 534 } |
| 535 |
| 536 NFCMessage toNFCMessage(const device::wtf::NFCMessagePtr& message, ScriptState*
scriptState) |
| 537 { |
| 538 NFCMessage nfcMessage; |
| 539 nfcMessage.setURL(message->url); |
| 540 blink::HeapVector<NFCRecord> records; |
| 541 for (size_t i = 0; i < message->data.size(); ++i) |
| 542 records.append(toNFCRecord(message->data[i], scriptState)); |
| 543 nfcMessage.setData(records); |
| 544 return nfcMessage; |
| 545 } |
| 546 |
433 } // anonymous namespace | 547 } // anonymous namespace |
434 | 548 |
| 549 template <typename T> |
| 550 class NFCCallbackBase { |
| 551 public: |
| 552 explicit NFCCallbackBase(ScriptPromiseResolver* resolver) |
| 553 : m_promiseAdapter(adoptPtr(new T(resolver))) { } |
| 554 |
| 555 // If NFCService is not available or disappears when NFC HW is disabled, |
| 556 // mojo service will invalidate proxy and destroy all pending callbacks. |
| 557 // Promise will be rejected with NotSupportedError exception. |
| 558 virtual ~NFCCallbackBase() |
| 559 { |
| 560 m_promiseAdapter->onError(device::wtf::NFCErrorType::NOT_SUPPORTED); |
| 561 } |
| 562 |
| 563 protected: |
| 564 OwnPtr<T> m_promiseAdapter; |
| 565 }; |
| 566 |
435 using NFCMojoCallback = mojo::Callback<void(device::wtf::NFCErrorPtr)>; | 567 using NFCMojoCallback = mojo::Callback<void(device::wtf::NFCErrorPtr)>; |
436 class NFCCallback final : public NFCMojoCallback::Runnable { | 568 using NFCCallbackPromiseAdapter = CallbackPromiseAdapter<void, NFCError>; |
| 569 |
| 570 class NFCCallback final : public NFCMojoCallback::Runnable, |
| 571 public NFCCallbackBase<NFCCallbackPromiseAdapter> { |
437 WTF_MAKE_NONCOPYABLE(NFCCallback); | 572 WTF_MAKE_NONCOPYABLE(NFCCallback); |
438 public: | 573 public: |
439 using NFCCallbackPromiseAdapter = CallbackPromiseAdapter<void, NFCError>; | |
440 explicit NFCCallback(ScriptPromiseResolver* resolver) | 574 explicit NFCCallback(ScriptPromiseResolver* resolver) |
441 : m_promiseAdapter(adoptPtr(new NFCCallbackPromiseAdapter(resolver))) { } | 575 : NFCCallbackBase<NFCCallbackPromiseAdapter>(resolver) { } |
442 | |
443 ~NFCCallback() override | |
444 { | |
445 // If NFCService is not available or disappears when NFC HW is disabled, | |
446 // reject promise with NotSupportedError exception. | |
447 m_promiseAdapter->onError(device::wtf::NFCErrorType::NOT_SUPPORTED); | |
448 } | |
449 | 576 |
450 void Run(device::wtf::NFCErrorPtr error) override | 577 void Run(device::wtf::NFCErrorPtr error) override |
451 { | 578 { |
452 if (error.is_null()) | 579 if (error.is_null()) |
453 m_promiseAdapter->onSuccess(); | 580 m_promiseAdapter->onSuccess(); |
454 else | 581 else |
455 m_promiseAdapter->onError(error->error_type); | 582 m_promiseAdapter->onError(error->error_type); |
456 } | 583 } |
| 584 }; |
| 585 |
| 586 using NFCWatchMojoCallback = mojo::Callback<void(uint32_t, device::wtf::NFCError
Ptr)>; |
| 587 using NFCWatchCallbackPromiseAdapter = CallbackPromiseAdapter<uint32_t, NFCError
>; |
| 588 |
| 589 class NFCWatchCallback final : public NFCWatchMojoCallback::Runnable, |
| 590 public NFCCallbackBase<NFCWatchCallbackPromiseAdapter> { |
| 591 WTF_MAKE_NONCOPYABLE(NFCWatchCallback); |
| 592 public: |
| 593 NFCWatchCallback(ScriptPromiseResolver* resolver, NFC* nfc, MessageCallback*
callback) |
| 594 : NFCCallbackBase<NFCWatchCallbackPromiseAdapter>(resolver) |
| 595 , m_nfc(nfc) |
| 596 , m_callback(callback) { } |
| 597 |
| 598 void Run(uint32_t watchId, device::wtf::NFCErrorPtr error) override |
| 599 { |
| 600 if (error.is_null()) { |
| 601 m_nfc->OnWatchRegistered(watchId, m_callback); |
| 602 m_promiseAdapter->onSuccess(watchId); |
| 603 } else { |
| 604 m_promiseAdapter->onError(error->error_type); |
| 605 } |
| 606 } |
457 | 607 |
458 private: | 608 private: |
459 OwnPtr<NFCCallbackPromiseAdapter> m_promiseAdapter; | 609 Persistent<NFC> m_nfc; |
| 610 Persistent<MessageCallback> m_callback; |
460 }; | 611 }; |
461 | 612 |
462 NFC::NFC(LocalFrame* frame) | 613 NFC::NFC(LocalFrame* frame) |
463 : PageLifecycleObserver(frame ? frame->page() : 0), | 614 : PageLifecycleObserver(frame ? frame->page() : 0), |
464 m_client(this) | 615 m_client(this) |
465 { | 616 { |
466 } | 617 } |
467 | 618 |
468 NFC* NFC::create(LocalFrame* frame) | 619 NFC* NFC::create(LocalFrame* frame) |
469 { | 620 { |
470 NFC* nfc = new NFC(frame); | 621 NFC* nfc = new NFC(frame); |
471 return nfc; | 622 return nfc; |
472 } | 623 } |
473 | 624 |
474 NFC::~NFC() = default; | 625 NFC::~NFC() = default; |
475 | 626 |
476 // https://w3c.github.io/web-nfc/#writing-or-pushing-content | 627 // https://w3c.github.io/web-nfc/#writing-or-pushing-content |
| 628 // https://w3c.github.io/web-nfc/#dom-nfc-push |
477 ScriptPromise NFC::push(ScriptState* scriptState, const NFCPushMessage& pushMess
age, const NFCPushOptions& options) | 629 ScriptPromise NFC::push(ScriptState* scriptState, const NFCPushMessage& pushMess
age, const NFCPushOptions& options) |
478 { | 630 { |
479 String errorMessage; | 631 ScriptPromise promise = RejectIfNotSupported(scriptState); |
480 if (!scriptState->getExecutionContext()->isSecureContext(errorMessage)) { | 632 if (!promise.isEmpty()) |
481 return ScriptPromise::rejectWithDOMException(scriptState, DOMException::
create(SecurityError, errorMessage)); | 633 return promise; |
482 } | |
483 | 634 |
484 DOMException* exception = isValidNFCPushMessage(pushMessage); | 635 DOMException* exception = isValidNFCPushMessage(pushMessage); |
485 if (exception) | 636 if (exception) |
486 return ScriptPromise::rejectWithDOMException(scriptState, exception); | 637 return ScriptPromise::rejectWithDOMException(scriptState, exception); |
487 | 638 |
488 if (!Initialize(scriptState->domWindow()->frame()->serviceRegistry())) | |
489 return ScriptPromise::rejectWithDOMException(scriptState, DOMException::
create(NotSupportedError)); | |
490 | |
491 device::wtf::NFCMessagePtr message = device::wtf::NFCMessage::From(pushMessa
ge); | 639 device::wtf::NFCMessagePtr message = device::wtf::NFCMessage::From(pushMessa
ge); |
492 if (!message) | 640 if (!message) |
493 return ScriptPromise::rejectWithDOMException(scriptState, DOMException::
create(SyntaxError)); | 641 return ScriptPromise::rejectWithDOMException(scriptState, DOMException::
create(SyntaxError)); |
494 | 642 |
495 if (!setURL(scriptState->getExecutionContext()->getSecurityOrigin()->toStrin
g(), message)) | 643 if (!setURL(scriptState->getExecutionContext()->getSecurityOrigin()->toStrin
g(), message)) |
496 return ScriptPromise::rejectWithDOMException(scriptState, DOMException::
create(SyntaxError)); | 644 return ScriptPromise::rejectWithDOMException(scriptState, DOMException::
create(SyntaxError)); |
497 | 645 |
498 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; | 646 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; |
499 m_nfc->Push(std::move(message), device::wtf::NFCPushOptions::From(options),
device::wtf::NFC::PushCallback(new NFCCallback(resolver))); | 647 m_nfc->Push(std::move(message), device::wtf::NFCPushOptions::From(options),
device::wtf::NFC::PushCallback(new NFCCallback(resolver))); |
500 | 648 |
501 return resolver->promise(); | 649 return resolver->promise(); |
502 } | 650 } |
503 | 651 |
| 652 // https://w3c.github.io/web-nfc/#dom-nfc-cancelpush |
504 ScriptPromise NFC::cancelPush(ScriptState* scriptState, const String& target) | 653 ScriptPromise NFC::cancelPush(ScriptState* scriptState, const String& target) |
505 { | 654 { |
506 String errorMessage; | 655 ScriptPromise promise = RejectIfNotSupported(scriptState); |
507 if (!scriptState->getExecutionContext()->isSecureContext(errorMessage)) { | 656 if (!promise.isEmpty()) |
508 return ScriptPromise::rejectWithDOMException(scriptState, DOMException::
create(SecurityError, errorMessage)); | 657 return promise; |
509 } | |
510 | |
511 if (!Initialize(scriptState->domWindow()->frame()->serviceRegistry())) | |
512 return ScriptPromise::rejectWithDOMException(scriptState, DOMException::
create(NotSupportedError)); | |
513 | 658 |
514 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; | 659 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; |
515 m_nfc->CancelPush(mojo::toNFCPushTarget(target), device::wtf::NFC::CancelPus
hCallback(new NFCCallback(resolver))); | 660 m_nfc->CancelPush(mojo::toNFCPushTarget(target), device::wtf::NFC::CancelPus
hCallback(new NFCCallback(resolver))); |
516 | 661 |
517 return resolver->promise(); | 662 return resolver->promise(); |
518 } | 663 } |
519 | 664 |
| 665 // https://w3c.github.io/web-nfc/#watching-for-content |
| 666 // https://w3c.github.io/web-nfc/#dom-nfc-watch |
520 ScriptPromise NFC::watch(ScriptState* scriptState, MessageCallback* callback, co
nst NFCWatchOptions& options) | 667 ScriptPromise NFC::watch(ScriptState* scriptState, MessageCallback* callback, co
nst NFCWatchOptions& options) |
521 { | 668 { |
522 // TODO(shalamov): To be implemented. | 669 ScriptPromise promise = RejectIfNotSupported(scriptState); |
523 return ScriptPromise::rejectWithDOMException(scriptState, DOMException::crea
te(NotSupportedError)); | 670 if (!promise.isEmpty()) |
| 671 return promise; |
| 672 |
| 673 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; |
| 674 device::wtf::NFC::WatchCallback watchCallback(new NFCWatchCallback(resolver,
this, callback)); |
| 675 m_nfc->Watch(device::wtf::NFCWatchOptions::From(options), watchCallback); |
| 676 return resolver->promise(); |
524 } | 677 } |
525 | 678 |
| 679 // https://w3c.github.io/web-nfc/#dom-nfc-cancelwatch |
526 ScriptPromise NFC::cancelWatch(ScriptState* scriptState, long id) | 680 ScriptPromise NFC::cancelWatch(ScriptState* scriptState, long id) |
527 { | 681 { |
528 // TODO(shalamov): To be implemented. | 682 ScriptPromise promise = RejectIfNotSupported(scriptState); |
529 return ScriptPromise::rejectWithDOMException(scriptState, DOMException::crea
te(NotSupportedError)); | 683 if (!promise.isEmpty()) |
| 684 return promise; |
| 685 |
| 686 if (id) |
| 687 m_callbacks.remove(id); |
| 688 else |
| 689 return ScriptPromise::rejectWithDOMException(scriptState, DOMException::
create(NotFoundError)); |
| 690 |
| 691 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; |
| 692 m_nfc->CancelWatch(id, device::wtf::NFC::CancelWatchCallback(new NFCCallback
(resolver))); |
| 693 return resolver->promise(); |
530 } | 694 } |
531 | 695 |
| 696 // https://w3c.github.io/web-nfc/#dom-nfc-cancelwatch |
| 697 // If watchId is not provided to nfc.cancelWatch, cancel all watch operations. |
532 ScriptPromise NFC::cancelWatch(ScriptState* scriptState) | 698 ScriptPromise NFC::cancelWatch(ScriptState* scriptState) |
533 { | 699 { |
534 // TODO(shalamov): To be implemented. | 700 ScriptPromise promise = RejectIfNotSupported(scriptState); |
535 return ScriptPromise::rejectWithDOMException(scriptState, DOMException::crea
te(NotSupportedError)); | 701 if (!promise.isEmpty()) |
| 702 return promise; |
| 703 |
| 704 m_callbacks.clear(); |
| 705 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; |
| 706 m_nfc->CancelAllWatches(device::wtf::NFC::CancelAllWatchesCallback(new NFCCa
llback(resolver))); |
| 707 return resolver->promise(); |
536 } | 708 } |
537 | 709 |
538 void NFC::pageVisibilityChanged() | 710 void NFC::pageVisibilityChanged() |
539 { | 711 { |
540 // If service is not initialized, there cannot be any pending NFC activities | 712 // If service is not initialized, there cannot be any pending NFC activities |
541 if (!m_nfc) | 713 if (!m_nfc) |
542 return; | 714 return; |
543 | 715 |
544 // NFC operations should be suspended. | 716 // NFC operations should be suspended. |
545 // https://w3c.github.io/web-nfc/#nfc-suspended | 717 // https://w3c.github.io/web-nfc/#nfc-suspended |
546 if (page()->visibilityState() == PageVisibilityStateVisible) | 718 if (page()->visibilityState() == PageVisibilityStateVisible) |
547 m_nfc->ResumeNFCOperations(); | 719 m_nfc->ResumeNFCOperations(); |
548 else | 720 else |
549 m_nfc->SuspendNFCOperations(); | 721 m_nfc->SuspendNFCOperations(); |
550 } | 722 } |
551 | 723 |
552 void NFC::OnWatch(uint32_t id, device::wtf::NFCMessagePtr message) | 724 void NFC::OnWatch(uint32_t id, device::wtf::NFCMessagePtr message) |
553 { | 725 { |
| 726 WatchCallbacksMap::iterator it = m_callbacks.find(id); |
| 727 if (it != m_callbacks.end()) { |
| 728 ScriptState* scriptState = ScriptState::forMainWorld(toLocalFrame(page()
->mainFrame())); |
| 729 ScriptState::Scope scope(scriptState); |
| 730 it->value->handleMessage(toNFCMessage(message, scriptState)); |
| 731 } |
554 } | 732 } |
555 | 733 |
556 bool NFC::Initialize(ServiceRegistry* registry) | 734 bool NFC::Initialize(ServiceRegistry* registry) |
557 { | 735 { |
558 DCHECK(registry); | 736 DCHECK(registry); |
559 | 737 |
560 if (m_nfc) | 738 if (m_nfc) |
561 return true; | 739 return true; |
562 | 740 |
563 registry->connectToRemoteService(mojo::GetProxy(&m_nfc)); | 741 registry->connectToRemoteService(mojo::GetProxy(&m_nfc)); |
564 | 742 |
565 if (m_nfc) { | 743 if (m_nfc) { |
566 m_nfc.set_connection_error_handler(sameThreadBindForMojo(&NFC::OnError,
this)); | 744 m_nfc.set_connection_error_handler(sameThreadBindForMojo(&NFC::OnError,
this)); |
567 m_nfc->SetClient(m_client.CreateInterfacePtrAndBind()); | 745 m_nfc->SetClient(m_client.CreateInterfacePtrAndBind()); |
568 } | 746 } |
569 | 747 |
570 return m_nfc; | 748 return m_nfc; |
571 } | 749 } |
572 | 750 |
| 751 ScriptPromise NFC::RejectIfNotSupported(ScriptState* scriptState) |
| 752 { |
| 753 String errorMessage; |
| 754 if (!scriptState->getExecutionContext()->isSecureContext(errorMessage)) { |
| 755 return ScriptPromise::rejectWithDOMException(scriptState, DOMException::
create(SecurityError, errorMessage)); |
| 756 } |
| 757 |
| 758 if (!Initialize(scriptState->domWindow()->frame()->serviceRegistry())) |
| 759 return ScriptPromise::rejectWithDOMException(scriptState, DOMException::
create(NotSupportedError)); |
| 760 |
| 761 return ScriptPromise(); |
| 762 } |
| 763 |
573 void NFC::OnError() | 764 void NFC::OnError() |
574 { | 765 { |
575 // todo(shalamov): clear map that contains nfc watch callbacks | 766 m_callbacks.clear(); |
576 if (m_client.is_bound()) | 767 if (m_client.is_bound()) |
577 m_client.Close(); | 768 m_client.Close(); |
578 m_nfc.reset(); | 769 m_nfc.reset(); |
579 } | 770 } |
580 | 771 |
| 772 void NFC::OnWatchRegistered(uint32_t id, MessageCallback* callback) |
| 773 { |
| 774 if (id) |
| 775 m_callbacks.add(id, callback); |
| 776 } |
| 777 |
581 DEFINE_TRACE(NFC) | 778 DEFINE_TRACE(NFC) |
582 { | 779 { |
583 PageLifecycleObserver::trace(visitor); | 780 PageLifecycleObserver::trace(visitor); |
| 781 visitor->trace(m_callbacks); |
584 } | 782 } |
585 | 783 |
586 } // namespace blink | 784 } // namespace blink |
OLD | NEW |