Chromium Code Reviews| 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/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 | 21 |
| 21 namespace nfc = device::nfc::blink; | 22 namespace nfc = device::nfc::blink; |
| 22 | 23 |
| 23 namespace { | 24 namespace { |
| 24 const char kJsonMimePrefix[] = "application/"; | 25 const char kJsonMimePrefix[] = "application/"; |
| 25 const char kJsonMimeType[] = "application/json"; | 26 const char kJsonMimeType[] = "application/json"; |
| 26 const char kOpaqueMimeType[] = "application/octet-stream"; | 27 const char kOpaqueMimeType[] = "application/octet-stream"; |
| 27 const char kPlainTextMimeType[] = "text/plain"; | 28 const char kPlainTextMimeType[] = "text/plain"; |
| 28 const char kPlainTextMimePrefix[] = "text/"; | 29 const char kPlainTextMimePrefix[] = "text/"; |
| 29 const char kCharSetUTF8[] = ";charset=UTF-8"; | 30 const char kCharSetUTF8[] = ";charset=UTF-8"; |
| 30 } // anonymous namespace | 31 } // anonymous namespace |
| 31 | 32 |
| 32 // Mojo type converters | 33 // Mojo type converters |
| 33 namespace mojo { | 34 namespace mojo { |
| 34 | 35 |
| 35 using nfc::NFCMessage; | 36 using nfc::NFCMessage; |
| 36 using nfc::NFCMessagePtr; | 37 using nfc::NFCMessagePtr; |
| 37 using nfc::NFCRecord; | 38 using nfc::NFCRecord; |
| 38 using nfc::NFCRecordPtr; | 39 using nfc::NFCRecordPtr; |
| 39 using nfc::NFCRecordType; | 40 using nfc::NFCRecordType; |
| 41 using nfc::NFCRecordTypeFilter; | |
| 42 using nfc::NFCRecordTypeFilterPtr; | |
| 40 using nfc::NFCPushOptions; | 43 using nfc::NFCPushOptions; |
| 41 using nfc::NFCPushOptionsPtr; | 44 using nfc::NFCPushOptionsPtr; |
| 42 using nfc::NFCPushTarget; | 45 using nfc::NFCPushTarget; |
| 46 using nfc::NFCWatchMode; | |
| 47 using nfc::NFCWatchOptions; | |
| 48 using nfc::NFCWatchOptionsPtr; | |
| 43 | 49 |
| 44 NFCPushTarget toNFCPushTarget(const WTF::String& target) | 50 NFCPushTarget toNFCPushTarget(const WTF::String& target) |
| 45 { | 51 { |
| 46 if (target == "tag") | 52 if (target == "tag") |
| 47 return NFCPushTarget::TAG; | 53 return NFCPushTarget::TAG; |
| 48 | 54 |
| 49 if (target == "peer") | 55 if (target == "peer") |
| 50 return NFCPushTarget::PEER; | 56 return NFCPushTarget::PEER; |
| 51 | 57 |
| 52 return NFCPushTarget::ANY; | 58 return NFCPushTarget::ANY; |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 66 if (recordType == "json") | 72 if (recordType == "json") |
| 67 return NFCRecordType::JSON; | 73 return NFCRecordType::JSON; |
| 68 | 74 |
| 69 if (recordType == "opaque") | 75 if (recordType == "opaque") |
| 70 return NFCRecordType::OPAQUE_RECORD; | 76 return NFCRecordType::OPAQUE_RECORD; |
| 71 | 77 |
| 72 NOTREACHED(); | 78 NOTREACHED(); |
| 73 return NFCRecordType::EMPTY; | 79 return NFCRecordType::EMPTY; |
| 74 } | 80 } |
| 75 | 81 |
| 82 NFCWatchMode toNFCWatchMode(const WTF::String& watchMode) | |
| 83 { | |
| 84 if (watchMode == "web-nfc-only") | |
| 85 return NFCWatchMode::WEBNFC_ONLY; | |
| 86 | |
| 87 if (watchMode == "any") | |
| 88 return NFCWatchMode::ANY; | |
| 89 | |
| 90 NOTREACHED(); | |
| 91 return NFCWatchMode::WEBNFC_ONLY; | |
| 92 } | |
| 93 | |
| 76 // https://w3c.github.io/web-nfc/#creating-web-nfc-message Step 2.1 | 94 // https://w3c.github.io/web-nfc/#creating-web-nfc-message Step 2.1 |
| 77 // If NFCRecord type is not provided, deduce NFCRecord type from JS data type: | 95 // If NFCRecord type is not provided, deduce NFCRecord type from JS data type: |
| 78 // String or Number => 'text' record | 96 // String or Number => 'text' record |
| 79 // ArrayBuffer => 'opaque' record | 97 // ArrayBuffer => 'opaque' record |
| 80 // JSON serializable Object => 'json' record | 98 // JSON serializable Object => 'json' record |
| 81 NFCRecordType deduceRecordTypeFromDataType(const blink::NFCRecord& record) | 99 NFCRecordType deduceRecordTypeFromDataType(const blink::NFCRecord& record) |
| 82 { | 100 { |
| 83 if (record.hasData()) { | 101 if (record.hasData()) { |
| 84 v8::Local<v8::Value> value = record.data().v8Value(); | 102 v8::Local<v8::Value> value = record.data().v8Value(); |
| 85 | 103 |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 304 | 322 |
| 305 if (pushOptions.hasIgnoreRead()) | 323 if (pushOptions.hasIgnoreRead()) |
| 306 pushOptionsPtr->ignore_read = pushOptions.ignoreRead(); | 324 pushOptionsPtr->ignore_read = pushOptions.ignoreRead(); |
| 307 else | 325 else |
| 308 pushOptionsPtr->ignore_read = true; | 326 pushOptionsPtr->ignore_read = true; |
| 309 | 327 |
| 310 return pushOptionsPtr; | 328 return pushOptionsPtr; |
| 311 } | 329 } |
| 312 }; | 330 }; |
| 313 | 331 |
| 332 template <> | |
| 333 struct TypeConverter<NFCWatchOptionsPtr, blink::NFCWatchOptions> { | |
| 334 static NFCWatchOptionsPtr Convert(const blink::NFCWatchOptions& watchOptions ) | |
| 335 { | |
| 336 // https://w3c.github.io/web-nfc/#the-nfcwatchoptions-dictionary | |
| 337 // Default values for NFCWatchOptions dictionary are: | |
| 338 // url = "", recordType = null, mediaType = "", mode = "web-nfc-only" | |
| 339 NFCWatchOptionsPtr watchOptionsPtr = NFCWatchOptions::New(); | |
| 340 watchOptionsPtr->url = watchOptions.url(); | |
| 341 watchOptionsPtr->media_type = watchOptions.mediaType(); | |
| 342 | |
| 343 if (watchOptions.hasMode()) | |
| 344 watchOptionsPtr->mode = toNFCWatchMode(watchOptions.mode()); | |
| 345 else | |
| 346 watchOptionsPtr->mode = NFCWatchMode::WEBNFC_ONLY; | |
| 347 | |
| 348 if (watchOptions.hasRecordType()) { | |
| 349 watchOptionsPtr->record_filter = NFCRecordTypeFilter::New(); | |
| 350 watchOptionsPtr->record_filter->record_type = toNFCRecordType(watchO ptions.recordType()); | |
| 351 } | |
| 352 | |
| 353 return watchOptionsPtr; | |
|
dcheng
2016/09/08 04:42:38
Please use a typemap instead (see https://www.chro
shalamov
2016/09/22 13:53:22
I don't think blink generated bindings <=> mojo ty
| |
| 354 } | |
| 355 }; | |
| 356 | |
| 314 } // namespace mojo | 357 } // namespace mojo |
| 315 | 358 |
| 316 namespace blink { | 359 namespace blink { |
| 317 namespace { | 360 namespace { |
| 318 | 361 |
| 319 bool isValidTextRecord(const NFCRecord& record) | 362 bool isValidTextRecord(const NFCRecord& record) |
| 320 { | 363 { |
| 321 v8::Local<v8::Value> value = record.data().v8Value(); | 364 v8::Local<v8::Value> value = record.data().v8Value(); |
| 322 if (!value->IsString() && !(value->IsNumber() && !std::isnan(value.As<v8::Nu mber>()->Value()))) | 365 if (!value->IsString() && !(value->IsNumber() && !std::isnan(value.As<v8::Nu mber>()->Value()))) |
| 323 return false; | 366 return false; |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 428 KURL originURL(ParsedURLString, origin); | 471 KURL originURL(ParsedURLString, origin); |
| 429 | 472 |
| 430 if (!message->url.isEmpty() && originURL.canSetPathname()) { | 473 if (!message->url.isEmpty() && originURL.canSetPathname()) { |
| 431 originURL.setPath(message->url); | 474 originURL.setPath(message->url); |
| 432 } | 475 } |
| 433 | 476 |
| 434 message->url = originURL; | 477 message->url = originURL; |
| 435 return originURL.isValid(); | 478 return originURL.isValid(); |
| 436 } | 479 } |
| 437 | 480 |
| 481 String toNFCRecordType(const nfc::NFCRecordType& type) | |
| 482 { | |
| 483 switch (type) { | |
| 484 case nfc::NFCRecordType::TEXT: | |
| 485 return "text"; | |
| 486 case nfc::NFCRecordType::URL: | |
| 487 return "url"; | |
| 488 case nfc::NFCRecordType::JSON: | |
| 489 return "json"; | |
| 490 case nfc::NFCRecordType::OPAQUE_RECORD: | |
| 491 return "opaque"; | |
| 492 case nfc::NFCRecordType::EMPTY: | |
| 493 return "empty"; | |
| 494 } | |
| 495 | |
| 496 NOTREACHED(); | |
| 497 return String(); | |
| 498 } | |
| 499 | |
| 500 v8::Local<v8::Value> toV8(const nfc::NFCRecordPtr& record, ScriptState* scriptSt ate) | |
|
dcheng
2016/09/08 04:42:38
Why do we need to do this manually? I would expect
shalamov
2016/09/22 13:53:22
NFCRecord is a kind of container Type,Mime,Data. V
| |
| 501 { | |
| 502 switch (record->record_type) { | |
| 503 case nfc::NFCRecordType::TEXT: | |
| 504 case nfc::NFCRecordType::URL: | |
| 505 case nfc::NFCRecordType::JSON: { | |
| 506 String stringData; | |
| 507 if (!record->data.empty()) | |
| 508 stringData = String::fromUTF8WithLatin1Fallback(static_cast<unsigned char*>(&record->data.front()), record->data.size()); | |
| 509 | |
| 510 if (record->record_type == nfc::NFCRecordType::JSON) | |
| 511 return v8::JSON::Parse(scriptState->isolate(), v8String(scriptState- >isolate(), stringData)).ToLocalChecked(); | |
| 512 return v8String(scriptState->isolate(), stringData); | |
| 513 } | |
| 514 | |
| 515 case nfc::NFCRecordType::OPAQUE_RECORD: { | |
| 516 if (!record->data.empty()) { | |
| 517 DOMArrayBuffer* buffer = DOMArrayBuffer::create(static_cast<void*>(& record->data.front()), record->data.size()); | |
| 518 return toV8(buffer, scriptState->context()->Global(), scriptState->i solate()); | |
| 519 } | |
| 520 | |
| 521 return v8::Null(scriptState->isolate()); | |
| 522 } | |
| 523 | |
| 524 case nfc::NFCRecordType::EMPTY: | |
| 525 return v8::Null(scriptState->isolate()); | |
| 526 } | |
| 527 | |
| 528 NOTREACHED(); | |
| 529 return v8::Local<v8::Value>(); | |
| 530 } | |
| 531 | |
| 532 NFCRecord toNFCRecord(const nfc::NFCRecordPtr& record, ScriptState* scriptState) | |
| 533 { | |
| 534 NFCRecord nfcRecord; | |
| 535 nfcRecord.setMediaType(record->media_type); | |
| 536 nfcRecord.setRecordType(toNFCRecordType(record->record_type)); | |
| 537 nfcRecord.setData(ScriptValue(scriptState, toV8(record, scriptState))); | |
| 538 return nfcRecord; | |
| 539 } | |
| 540 | |
| 541 NFCMessage toNFCMessage(const nfc::NFCMessagePtr& message, ScriptState* scriptSt ate) | |
| 542 { | |
| 543 NFCMessage nfcMessage; | |
| 544 nfcMessage.setURL(message->url); | |
| 545 blink::HeapVector<NFCRecord> records; | |
| 546 for (size_t i = 0; i < message->data.size(); ++i) | |
| 547 records.append(toNFCRecord(message->data[i], scriptState)); | |
| 548 nfcMessage.setData(records); | |
| 549 return nfcMessage; | |
| 550 } | |
| 551 | |
| 552 size_t getNFCMessageSize(const nfc::NFCMessagePtr& message) | |
| 553 { | |
| 554 size_t messageSize = message->url.charactersSizeInBytes(); | |
| 555 for (size_t i = 0; i < message->data.size(); ++i) { | |
| 556 messageSize += message->data[i]->media_type.charactersSizeInBytes(); | |
| 557 messageSize += message->data[i]->data.size(); | |
| 558 } | |
| 559 return messageSize; | |
| 560 } | |
| 561 | |
| 438 } // anonymous namespace | 562 } // anonymous namespace |
| 439 | 563 |
| 440 NFC::NFC(LocalFrame* frame) | 564 NFC::NFC(LocalFrame* frame) |
| 441 : PageVisibilityObserver(frame->page()) | 565 : PageVisibilityObserver(frame->page()) |
| 442 , ContextLifecycleObserver(frame->document()) | 566 , ContextLifecycleObserver(frame->document()) |
| 443 , m_client(this) | 567 , m_client(this) |
| 444 { | 568 { |
| 445 ThreadState::current()->registerPreFinalizer(this); | 569 ThreadState::current()->registerPreFinalizer(this); |
| 446 frame->interfaceProvider()->getInterface(mojo::GetProxy(&m_nfc)); | 570 frame->interfaceProvider()->getInterface(mojo::GetProxy(&m_nfc)); |
| 447 m_nfc.set_connection_error_handler(convertToBaseCallback(WTF::bind(&NFC::OnC onnectionError, wrapWeakPersistent(this)))); | 571 m_nfc.set_connection_error_handler(convertToBaseCallback(WTF::bind(&NFC::OnC onnectionError, wrapWeakPersistent(this)))); |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 463 | 587 |
| 464 void NFC::dispose() | 588 void NFC::dispose() |
| 465 { | 589 { |
| 466 m_client.Close(); | 590 m_client.Close(); |
| 467 } | 591 } |
| 468 | 592 |
| 469 void NFC::contextDestroyed() | 593 void NFC::contextDestroyed() |
| 470 { | 594 { |
| 471 m_nfc.reset(); | 595 m_nfc.reset(); |
| 472 m_requests.clear(); | 596 m_requests.clear(); |
| 597 m_callbacks.clear(); | |
| 473 } | 598 } |
| 474 | 599 |
| 475 // https://w3c.github.io/web-nfc/#writing-or-pushing-content | 600 // https://w3c.github.io/web-nfc/#writing-or-pushing-content |
| 601 // https://w3c.github.io/web-nfc/#dom-nfc-push | |
| 476 ScriptPromise NFC::push(ScriptState* scriptState, const NFCPushMessage& pushMess age, const NFCPushOptions& options) | 602 ScriptPromise NFC::push(ScriptState* scriptState, const NFCPushMessage& pushMess age, const NFCPushOptions& options) |
| 477 { | 603 { |
| 478 String errorMessage; | 604 ScriptPromise promise = RejectIfNotSupported(scriptState); |
| 479 if (!scriptState->getExecutionContext()->isSecureContext(errorMessage)) | 605 if (!promise.isEmpty()) |
| 480 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(SecurityError, errorMessage)); | 606 return promise; |
| 481 | 607 |
| 482 DOMException* exception = isValidNFCPushMessage(pushMessage); | 608 DOMException* exception = isValidNFCPushMessage(pushMessage); |
| 483 if (exception) | 609 if (exception) |
| 484 return ScriptPromise::rejectWithDOMException(scriptState, exception); | 610 return ScriptPromise::rejectWithDOMException(scriptState, exception); |
| 485 | 611 |
| 486 if (!m_nfc) | |
| 487 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(NotSupportedError)); | |
| 488 | |
| 489 nfc::NFCMessagePtr message = nfc::NFCMessage::From(pushMessage); | 612 nfc::NFCMessagePtr message = nfc::NFCMessage::From(pushMessage); |
| 490 if (!message) | 613 if (!message) |
| 491 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(SyntaxError)); | 614 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(SyntaxError)); |
| 492 | 615 |
| 493 if (!setURL(scriptState->getExecutionContext()->getSecurityOrigin()->toStrin g(), message)) | 616 if (!setURL(scriptState->getExecutionContext()->getSecurityOrigin()->toStrin g(), message)) |
| 494 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(SyntaxError)); | 617 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(SyntaxError)); |
| 495 | 618 |
| 619 if (getNFCMessageSize(message) > nfc::NFCMessage::kMaxNFCMessageSize) | |
|
dcheng
2016/09/08 04:42:38
Do we have an equivalent check on the handling sid
shalamov
2016/09/22 13:53:22
We need two checks, one for push (write), one for
| |
| 620 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(NotSupportedError)); | |
| 621 | |
| 496 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ; | 622 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ; |
| 497 m_requests.add(resolver); | 623 m_requests.add(resolver); |
| 498 auto callback = convertToBaseCallback(WTF::bind(&NFC::OnRequestCompleted, wr apPersistent(this), wrapPersistent(resolver))); | 624 auto callback = convertToBaseCallback(WTF::bind(&NFC::OnRequestCompleted, wr apPersistent(this), wrapPersistent(resolver))); |
| 499 m_nfc->Push(std::move(message), nfc::NFCPushOptions::From(options), callback ); | 625 m_nfc->Push(std::move(message), nfc::NFCPushOptions::From(options), callback ); |
| 500 | 626 |
| 501 return resolver->promise(); | 627 return resolver->promise(); |
| 502 } | 628 } |
| 503 | 629 |
| 630 // https://w3c.github.io/web-nfc/#dom-nfc-cancelpush | |
| 504 ScriptPromise NFC::cancelPush(ScriptState* scriptState, const String& target) | 631 ScriptPromise NFC::cancelPush(ScriptState* scriptState, const String& target) |
| 505 { | 632 { |
| 506 String errorMessage; | 633 ScriptPromise promise = RejectIfNotSupported(scriptState); |
| 507 if (!scriptState->getExecutionContext()->isSecureContext(errorMessage)) | 634 if (!promise.isEmpty()) |
| 508 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(SecurityError, errorMessage)); | 635 return promise; |
| 509 | |
| 510 if (!m_nfc) | |
| 511 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(NotSupportedError)); | |
| 512 | 636 |
| 513 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ; | 637 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ; |
| 514 m_requests.add(resolver); | 638 m_requests.add(resolver); |
| 515 auto callback = convertToBaseCallback(WTF::bind(&NFC::OnRequestCompleted, wr apPersistent(this), wrapPersistent(resolver))); | 639 auto callback = convertToBaseCallback(WTF::bind(&NFC::OnRequestCompleted, wr apPersistent(this), wrapPersistent(resolver))); |
| 516 m_nfc->CancelPush(mojo::toNFCPushTarget(target), callback); | 640 m_nfc->CancelPush(mojo::toNFCPushTarget(target), callback); |
| 517 | 641 |
| 518 return resolver->promise(); | 642 return resolver->promise(); |
| 519 } | 643 } |
| 520 | 644 |
| 645 // https://w3c.github.io/web-nfc/#watching-for-content | |
| 646 // https://w3c.github.io/web-nfc/#dom-nfc-watch | |
| 521 ScriptPromise NFC::watch(ScriptState* scriptState, MessageCallback* callback, co nst NFCWatchOptions& options) | 647 ScriptPromise NFC::watch(ScriptState* scriptState, MessageCallback* callback, co nst NFCWatchOptions& options) |
| 522 { | 648 { |
| 523 // TODO(shalamov): To be implemented. | 649 ScriptPromise promise = RejectIfNotSupported(scriptState); |
| 524 return ScriptPromise::rejectWithDOMException(scriptState, DOMException::crea te(NotSupportedError)); | 650 if (!promise.isEmpty()) |
| 651 return promise; | |
| 652 | |
| 653 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ; | |
| 654 m_requests.add(resolver); | |
| 655 auto watchCallback = convertToBaseCallback(WTF::bind(&NFC::OnWatchRegistered , wrapPersistent(this), wrapPersistent(callback), wrapPersistent(resolver))); | |
| 656 m_nfc->Watch(nfc::NFCWatchOptions::From(options), watchCallback); | |
| 657 return resolver->promise(); | |
| 525 } | 658 } |
| 526 | 659 |
| 660 // https://w3c.github.io/web-nfc/#dom-nfc-cancelwatch | |
| 527 ScriptPromise NFC::cancelWatch(ScriptState* scriptState, long id) | 661 ScriptPromise NFC::cancelWatch(ScriptState* scriptState, long id) |
| 528 { | 662 { |
| 529 // TODO(shalamov): To be implemented. | 663 ScriptPromise promise = RejectIfNotSupported(scriptState); |
| 530 return ScriptPromise::rejectWithDOMException(scriptState, DOMException::crea te(NotSupportedError)); | 664 if (!promise.isEmpty()) |
| 665 return promise; | |
| 666 | |
| 667 if (id) | |
| 668 m_callbacks.remove(id); | |
| 669 else | |
| 670 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(NotFoundError)); | |
| 671 | |
| 672 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ; | |
| 673 m_requests.add(resolver); | |
| 674 m_nfc->CancelWatch(id, convertToBaseCallback(WTF::bind(&NFC::OnRequestComple ted, wrapPersistent(this), wrapPersistent(resolver)))); | |
| 675 return resolver->promise(); | |
| 531 } | 676 } |
| 532 | 677 |
| 678 // https://w3c.github.io/web-nfc/#dom-nfc-cancelwatch | |
| 679 // If watchId is not provided to nfc.cancelWatch, cancel all watch operations. | |
| 533 ScriptPromise NFC::cancelWatch(ScriptState* scriptState) | 680 ScriptPromise NFC::cancelWatch(ScriptState* scriptState) |
| 534 { | 681 { |
| 535 // TODO(shalamov): To be implemented. | 682 ScriptPromise promise = RejectIfNotSupported(scriptState); |
| 536 return ScriptPromise::rejectWithDOMException(scriptState, DOMException::crea te(NotSupportedError)); | 683 if (!promise.isEmpty()) |
| 684 return promise; | |
| 685 | |
| 686 m_callbacks.clear(); | |
| 687 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ; | |
| 688 m_requests.add(resolver); | |
| 689 m_nfc->CancelAllWatches(convertToBaseCallback(WTF::bind(&NFC::OnRequestCompl eted, wrapPersistent(this), wrapPersistent(resolver)))); | |
| 690 return resolver->promise(); | |
| 537 } | 691 } |
| 538 | 692 |
| 539 void NFC::pageVisibilityChanged() | 693 void NFC::pageVisibilityChanged() |
| 540 { | 694 { |
| 541 // If service is not initialized, there cannot be any pending NFC activities | 695 // If service is not initialized, there cannot be any pending NFC activities |
| 542 if (!m_nfc) | 696 if (!m_nfc) |
| 543 return; | 697 return; |
| 544 | 698 |
| 545 // NFC operations should be suspended. | 699 // NFC operations should be suspended. |
| 546 // https://w3c.github.io/web-nfc/#nfc-suspended | 700 // https://w3c.github.io/web-nfc/#nfc-suspended |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 558 m_requests.remove(resolver); | 712 m_requests.remove(resolver); |
| 559 if (error.is_null()) | 713 if (error.is_null()) |
| 560 resolver->resolve(); | 714 resolver->resolve(); |
| 561 else | 715 else |
| 562 resolver->reject(NFCError::take(resolver, error->error_type)); | 716 resolver->reject(NFCError::take(resolver, error->error_type)); |
| 563 } | 717 } |
| 564 | 718 |
| 565 void NFC::OnConnectionError() | 719 void NFC::OnConnectionError() |
| 566 { | 720 { |
| 567 m_nfc.reset(); | 721 m_nfc.reset(); |
| 722 m_callbacks.clear(); | |
| 568 | 723 |
| 569 // If NFCService is not available or disappears when NFC hardware is | 724 // If NFCService is not available or disappears when NFC hardware is |
| 570 // disabled, reject promise with NotSupportedError exception. | 725 // disabled, reject promise with NotSupportedError exception. |
| 571 for (ScriptPromiseResolver* resolver : m_requests) | 726 for (ScriptPromiseResolver* resolver : m_requests) |
| 572 resolver->reject(NFCError::take(resolver, nfc::NFCErrorType::NOT_SUPPORT ED)); | 727 resolver->reject(NFCError::take(resolver, nfc::NFCErrorType::NOT_SUPPORT ED)); |
| 573 | 728 |
| 574 m_requests.clear(); | 729 m_requests.clear(); |
| 575 } | 730 } |
| 576 | 731 |
| 577 void NFC::OnWatch(mojo::WTFArray<uint32_t> ids, nfc::NFCMessagePtr) | 732 void NFC::OnWatch(mojo::WTFArray<uint32_t> ids, nfc::NFCMessagePtr message) |
| 578 { | 733 { |
| 579 // TODO(shalamov): Not implemented. | 734 ScriptState* scriptState = ScriptState::forMainWorld(toLocalFrame(page()->ma inFrame())); |
|
dcheng
2016/09/08 04:42:38
Why does this always use the main frame? Can this
shalamov
2016/09/22 13:53:22
I added comment, according to the specification, a
| |
| 735 ScriptState::Scope scope(scriptState); | |
| 736 NFCMessage nfcMessage = toNFCMessage(message, scriptState); | |
| 737 | |
| 738 for (size_t i = 0; i < ids.size(); ++i) { | |
| 739 WatchCallbacksMap::iterator it = m_callbacks.find(ids[i]); | |
| 740 if (it != m_callbacks.end()) { | |
| 741 it->value->handleMessage(nfcMessage); | |
| 742 } | |
| 743 } | |
| 744 } | |
| 745 | |
| 746 ScriptPromise NFC::RejectIfNotSupported(ScriptState* scriptState) | |
| 747 { | |
| 748 String errorMessage; | |
| 749 if (!scriptState->getExecutionContext()->isSecureContext(errorMessage)) { | |
| 750 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(SecurityError, errorMessage)); | |
| 751 } | |
| 752 | |
| 753 if (!m_nfc) | |
| 754 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(NotSupportedError)); | |
| 755 | |
| 756 return ScriptPromise(); | |
| 757 } | |
| 758 | |
| 759 void NFC::OnWatchRegistered(MessageCallback* callback, ScriptPromiseResolver* re solver, uint32_t id, nfc::NFCErrorPtr error) | |
| 760 { | |
| 761 m_requests.remove(resolver); | |
| 762 | |
| 763 // Invalid id was returned. | |
| 764 // https://w3c.github.io/web-nfc/#dom-nfc-watch | |
| 765 // 8. If the request fails, reject promise with "NotSupportedError" | |
| 766 // and abort these steps. | |
| 767 if (!id) { | |
| 768 resolver->reject(NFCError::take(resolver, nfc::NFCErrorType::NOT_SUPPORT ED)); | |
| 769 return; | |
| 770 } | |
| 771 | |
| 772 if (error.is_null()) { | |
| 773 m_callbacks.add(id, callback); | |
| 774 resolver->resolve(id); | |
| 775 } else { | |
| 776 resolver->reject(NFCError::take(resolver, error->error_type)); | |
| 777 } | |
| 580 } | 778 } |
| 581 | 779 |
| 582 DEFINE_TRACE(NFC) | 780 DEFINE_TRACE(NFC) |
| 583 { | 781 { |
| 584 PageVisibilityObserver::trace(visitor); | 782 PageVisibilityObserver::trace(visitor); |
| 585 ContextLifecycleObserver::trace(visitor); | 783 ContextLifecycleObserver::trace(visitor); |
| 586 visitor->trace(m_requests); | 784 visitor->trace(m_requests); |
| 785 visitor->trace(m_callbacks); | |
| 587 } | 786 } |
| 588 | 787 |
| 589 } // namespace blink | 788 } // namespace blink |
| OLD | NEW |