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/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 |