OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2013 Apple Inc. All rights reserved. | 2 * Copyright (C) 2013 Apple Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
145 } | 145 } |
146 | 146 |
147 // A class holding a pending action. | 147 // A class holding a pending action. |
148 class MediaKeySession::PendingAction | 148 class MediaKeySession::PendingAction |
149 : public GarbageCollectedFinalized<MediaKeySession::PendingAction> { | 149 : public GarbageCollectedFinalized<MediaKeySession::PendingAction> { |
150 public: | 150 public: |
151 enum Type { GenerateRequest, Load, Update, Close, Remove }; | 151 enum Type { GenerateRequest, Load, Update, Close, Remove }; |
152 | 152 |
153 Type getType() const { return m_type; } | 153 Type getType() const { return m_type; } |
154 | 154 |
155 const Persistent<ContentDecryptionModuleResult> result() const { | 155 ContentDecryptionModuleResult* result() const { return m_result; } |
156 return m_result; | |
157 } | |
158 | 156 |
159 DOMArrayBuffer* data() const { | 157 DOMArrayBuffer* data() const { |
160 DCHECK(m_type == GenerateRequest || m_type == Update); | 158 DCHECK(m_type == GenerateRequest || m_type == Update); |
161 return m_data; | 159 return m_data; |
162 } | 160 } |
163 | 161 |
164 WebEncryptedMediaInitDataType initDataType() const { | 162 WebEncryptedMediaInitDataType initDataType() const { |
165 DCHECK_EQ(GenerateRequest, m_type); | 163 DCHECK_EQ(GenerateRequest, m_type); |
166 return m_initDataType; | 164 return m_initDataType; |
167 } | 165 } |
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
507 DOMArrayBuffer::create(initData.data(), initData.byteLength()); | 505 DOMArrayBuffer::create(initData.data(), initData.byteLength()); |
508 | 506 |
509 // 8. Let session type be this object's session type. | 507 // 8. Let session type be this object's session type. |
510 // (Done in constructor.) | 508 // (Done in constructor.) |
511 | 509 |
512 // 9. Let promise be a new promise. | 510 // 9. Let promise be a new promise. |
513 NewSessionResultPromise* result = | 511 NewSessionResultPromise* result = |
514 new NewSessionResultPromise(scriptState, this); | 512 new NewSessionResultPromise(scriptState, this); |
515 ScriptPromise promise = result->promise(); | 513 ScriptPromise promise = result->promise(); |
516 | 514 |
517 // 10. Run the following steps asynchronously (documented in | 515 // 10. Run the following steps asynchronously (done in generateRequestTask()) |
518 // actionTimerFired()) | |
519 m_pendingActions.append(PendingAction::CreatePendingGenerateRequest( | 516 m_pendingActions.append(PendingAction::CreatePendingGenerateRequest( |
520 result, initDataType, initDataBuffer)); | 517 result, initDataType, initDataBuffer)); |
521 DCHECK(!m_actionTimer.isActive()); | 518 DCHECK(!m_actionTimer.isActive()); |
522 m_actionTimer.startOneShot(0, BLINK_FROM_HERE); | 519 m_actionTimer.startOneShot(0, BLINK_FROM_HERE); |
523 | 520 |
524 // 11. Return promise. | 521 // 11. Return promise. |
525 return promise; | 522 return promise; |
526 } | 523 } |
527 | 524 |
| 525 void MediaKeySession::generateRequestTask( |
| 526 ContentDecryptionModuleResult* result, |
| 527 WebEncryptedMediaInitDataType initDataType, |
| 528 DOMArrayBuffer* initDataBuffer) { |
| 529 // NOTE: Continue step 10 of MediaKeySession::generateRequest(). |
| 530 DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ")"; |
| 531 |
| 532 // initializeNewSession() in Chromium will execute steps 10.1 to 10.9. |
| 533 m_session->initializeNewSession( |
| 534 initDataType, static_cast<unsigned char*>(initDataBuffer->data()), |
| 535 initDataBuffer->byteLength(), m_sessionType, result->result()); |
| 536 |
| 537 // Remaining steps (10.10) executed in finishGenerateRequest(), |
| 538 // called when |result| is resolved. |
| 539 } |
| 540 |
| 541 void MediaKeySession::finishGenerateRequest() { |
| 542 // NOTE: Continue step 10.10 of MediaKeySession::generateRequest(). |
| 543 DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ")"; |
| 544 |
| 545 // 10.10.1 If any of the preceding steps failed, reject promise with a |
| 546 // new DOMException whose name is the appropriate error name. |
| 547 // (Done by CDM calling result.completeWithError() as appropriate.) |
| 548 // 10.10.2 Set the sessionId attribute to session id. |
| 549 DCHECK(!sessionId().isEmpty()); |
| 550 |
| 551 // 10.10.3 Let this object's callable be true. |
| 552 m_isCallable = true; |
| 553 |
| 554 // 10.10.4 Run the Queue a "message" Event algorithm on the session, |
| 555 // providing message type and message. |
| 556 // (Done by the CDM.) |
| 557 // 10.10.5 Resolve promise. |
| 558 // (Done by NewSessionResultPromise.) |
| 559 } |
| 560 |
528 ScriptPromise MediaKeySession::load(ScriptState* scriptState, | 561 ScriptPromise MediaKeySession::load(ScriptState* scriptState, |
529 const String& sessionId) { | 562 const String& sessionId) { |
530 DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ") " | 563 DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ") " |
531 << sessionId; | 564 << sessionId; |
532 | 565 |
533 // From https://w3c.github.io/encrypted-media/#load: | 566 // From https://w3c.github.io/encrypted-media/#load: |
534 // Loads the data stored for the specified session into this object. When | 567 // Loads the data stored for the specified session into this object. When |
535 // this method is invoked, the user agent must run the following steps: | 568 // this method is invoked, the user agent must run the following steps: |
536 | 569 |
537 // 1. If this object is closed, return a promise rejected with an | 570 // 1. If this object is closed, return a promise rejected with an |
(...skipping 29 matching lines...) Expand all Loading... |
567 } | 600 } |
568 | 601 |
569 // 6. Let origin be the origin of this object's Document. | 602 // 6. Let origin be the origin of this object's Document. |
570 // (Available as getExecutionContext()->getSecurityOrigin() anytime.) | 603 // (Available as getExecutionContext()->getSecurityOrigin() anytime.) |
571 | 604 |
572 // 7. Let promise be a new promise. | 605 // 7. Let promise be a new promise. |
573 LoadSessionResultPromise* result = | 606 LoadSessionResultPromise* result = |
574 new LoadSessionResultPromise(scriptState, this); | 607 new LoadSessionResultPromise(scriptState, this); |
575 ScriptPromise promise = result->promise(); | 608 ScriptPromise promise = result->promise(); |
576 | 609 |
577 // 8. Run the following steps asynchronously (documented in | 610 // 8. Run the following steps asynchronously (done in loadTask()) |
578 // actionTimerFired()) | |
579 m_pendingActions.append( | 611 m_pendingActions.append( |
580 PendingAction::CreatePendingLoadRequest(result, sessionId)); | 612 PendingAction::CreatePendingLoadRequest(result, sessionId)); |
581 DCHECK(!m_actionTimer.isActive()); | 613 DCHECK(!m_actionTimer.isActive()); |
582 m_actionTimer.startOneShot(0, BLINK_FROM_HERE); | 614 m_actionTimer.startOneShot(0, BLINK_FROM_HERE); |
583 | 615 |
584 // 9. Return promise. | 616 // 9. Return promise. |
585 return promise; | 617 return promise; |
586 } | 618 } |
587 | 619 |
| 620 void MediaKeySession::loadTask(ContentDecryptionModuleResult* result, |
| 621 const String& sessionId) { |
| 622 // NOTE: Continue step 8 of MediaKeySession::load(). |
| 623 DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ")"; |
| 624 |
| 625 // 8.1 Let sanitized session ID be a validated and/or sanitized |
| 626 // version of sessionId. The user agent should thoroughly |
| 627 // validate the sessionId value before passing it to the CDM. |
| 628 // At a minimum, this should include checking that the length |
| 629 // and value (e.g. alphanumeric) are reasonable. |
| 630 // 8.2 If the preceding step failed, or if sanitized session ID |
| 631 // is empty, reject promise with a newly created TypeError. |
| 632 if (!isValidSessionId(sessionId)) { |
| 633 result->completeWithError(WebContentDecryptionModuleExceptionTypeError, 0, |
| 634 "Invalid sessionId"); |
| 635 return; |
| 636 } |
| 637 |
| 638 // 8.3 If there is an unclosed session in the object's Document |
| 639 // whose sessionId attribute is sanitized session ID, reject |
| 640 // promise with a new DOMException whose name is |
| 641 // QuotaExceededError. In other words, do not create a session |
| 642 // if a non-closed session, regardless of type, already exists |
| 643 // for this sanitized session ID in this browsing context. |
| 644 // (Done in the CDM.) |
| 645 |
| 646 // 8.4 Let expiration time be NaN. |
| 647 // (Done in the constructor.) |
| 648 DCHECK(std::isnan(m_expiration)); |
| 649 |
| 650 // load() in Chromium will execute steps 8.5 through 8.8. |
| 651 m_session->load(sessionId, result->result()); |
| 652 |
| 653 // Remaining step (8.9) executed in finishLoad(), called when |result| |
| 654 // is resolved. |
| 655 } |
| 656 |
| 657 void MediaKeySession::finishLoad() { |
| 658 // NOTE: Continue step 8.9 of MediaKeySession::load(). |
| 659 DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ")"; |
| 660 |
| 661 // 8.9.1 If any of the preceding steps failed, reject promise with a new |
| 662 // DOMException whose name is the appropriate error name. |
| 663 // (Done by CDM calling result.completeWithError() as appropriate.) |
| 664 |
| 665 // 8.9.2 Set the sessionId attribute to sanitized session ID. |
| 666 DCHECK(!sessionId().isEmpty()); |
| 667 |
| 668 // 8.9.3 Let this object's callable be true. |
| 669 m_isCallable = true; |
| 670 |
| 671 // 8.9.4 If the loaded session contains information about any keys (there |
| 672 // are known keys), run the update key statuses algorithm on the |
| 673 // session, providing each key's key ID along with the appropriate |
| 674 // MediaKeyStatus. Should additional processing be necessary to |
| 675 // determine with certainty the status of a key, use the non-"usable" |
| 676 // MediaKeyStatus value that corresponds to the reason for the |
| 677 // additional processing. Once the additional processing for one or |
| 678 // more keys has completed, run the update key statuses algorithm |
| 679 // again if any of the statuses has changed. |
| 680 // (Done by the CDM.) |
| 681 |
| 682 // 8.9.5 Run the Update Expiration algorithm on the session, |
| 683 // providing expiration time. |
| 684 // (Done by the CDM.) |
| 685 |
| 686 // 8.9.6 If message is not null, run the queue a "message" event algorithm |
| 687 // on the session, providing message type and message. |
| 688 // (Done by the CDM.) |
| 689 |
| 690 // 8.9.7 Resolve promise with true. |
| 691 // (Done by LoadSessionResultPromise.) |
| 692 } |
| 693 |
588 ScriptPromise MediaKeySession::update(ScriptState* scriptState, | 694 ScriptPromise MediaKeySession::update(ScriptState* scriptState, |
589 const DOMArrayPiece& response) { | 695 const DOMArrayPiece& response) { |
590 DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ")"; | 696 DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ")"; |
591 | 697 |
592 // From https://w3c.github.io/encrypted-media/#update: | 698 // From https://w3c.github.io/encrypted-media/#update: |
593 // Provides messages, including licenses, to the CDM. When this method is | 699 // Provides messages, including licenses, to the CDM. When this method is |
594 // invoked, the user agent must run the following steps: | 700 // invoked, the user agent must run the following steps: |
595 | 701 |
596 // 1. If this object is closed, return a promise rejected with an | 702 // 1. If this object is closed, return a promise rejected with an |
597 // InvalidStateError. | 703 // InvalidStateError. |
(...skipping 15 matching lines...) Expand all Loading... |
613 } | 719 } |
614 | 720 |
615 // 4. Let response copy be a copy of the contents of the response parameter. | 721 // 4. Let response copy be a copy of the contents of the response parameter. |
616 DOMArrayBuffer* responseCopy = | 722 DOMArrayBuffer* responseCopy = |
617 DOMArrayBuffer::create(response.data(), response.byteLength()); | 723 DOMArrayBuffer::create(response.data(), response.byteLength()); |
618 | 724 |
619 // 5. Let promise be a new promise. | 725 // 5. Let promise be a new promise. |
620 SimpleResultPromise* result = new SimpleResultPromise(scriptState, this); | 726 SimpleResultPromise* result = new SimpleResultPromise(scriptState, this); |
621 ScriptPromise promise = result->promise(); | 727 ScriptPromise promise = result->promise(); |
622 | 728 |
623 // 6. Run the following steps asynchronously (documented in | 729 // 6. Run the following steps asynchronously (done in updateTask()) |
624 // actionTimerFired()) | |
625 m_pendingActions.append( | 730 m_pendingActions.append( |
626 PendingAction::CreatePendingUpdate(result, responseCopy)); | 731 PendingAction::CreatePendingUpdate(result, responseCopy)); |
627 if (!m_actionTimer.isActive()) | 732 if (!m_actionTimer.isActive()) |
628 m_actionTimer.startOneShot(0, BLINK_FROM_HERE); | 733 m_actionTimer.startOneShot(0, BLINK_FROM_HERE); |
629 | 734 |
630 // 7. Return promise. | 735 // 7. Return promise. |
631 return promise; | 736 return promise; |
632 } | 737 } |
633 | 738 |
| 739 void MediaKeySession::updateTask(ContentDecryptionModuleResult* result, |
| 740 DOMArrayBuffer* sanitizedResponse) { |
| 741 // NOTE: Continue step 6 of MediaKeySession::update(). |
| 742 DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ")"; |
| 743 |
| 744 // update() in Chromium will execute steps 6.1 through 6.8. |
| 745 m_session->update(static_cast<unsigned char*>(sanitizedResponse->data()), |
| 746 sanitizedResponse->byteLength(), result->result()); |
| 747 |
| 748 // Last step (6.8.2 Resolve promise) will be done when |result| is resolved. |
| 749 } |
| 750 |
634 ScriptPromise MediaKeySession::close(ScriptState* scriptState) { | 751 ScriptPromise MediaKeySession::close(ScriptState* scriptState) { |
635 DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ")"; | 752 DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ")"; |
636 | 753 |
637 // From https://w3c.github.io/encrypted-media/#close: | 754 // From https://w3c.github.io/encrypted-media/#close: |
638 // Indicates that the application no longer needs the session and the CDM | 755 // Indicates that the application no longer needs the session and the CDM |
639 // should release any resources associated with this object and close it. | 756 // should release any resources associated with the session and close it. |
| 757 // Persisted data should not be released or cleared. |
640 // When this method is invoked, the user agent must run the following steps: | 758 // When this method is invoked, the user agent must run the following steps: |
641 | 759 |
642 // 1. If this object's callable value is false, return a promise rejected | 760 // 1. Let session be the associated MediaKeySession object. |
643 // with a new DOMException whose name is "InvalidStateError". | 761 // 2. If session is closed, return a resolved promise. |
| 762 if (m_isClosed) |
| 763 return ScriptPromise::cast(scriptState, ScriptValue()); |
| 764 |
| 765 // 3. If session's callable value is false, return a promise rejected with |
| 766 // an InvalidStateError. |
644 if (!m_isCallable) | 767 if (!m_isCallable) |
645 return CreateRejectedPromiseNotCallable(scriptState); | 768 return CreateRejectedPromiseNotCallable(scriptState); |
646 | 769 |
647 // 2. If the Session Close algorithm has been run on this object, | 770 // 4. Let promise be a new promise. |
648 // return a resolved promise. | |
649 if (m_isClosed) | |
650 return ScriptPromise::cast(scriptState, ScriptValue()); | |
651 | |
652 // 3. Let promise be a new promise. | |
653 SimpleResultPromise* result = new SimpleResultPromise(scriptState, this); | 771 SimpleResultPromise* result = new SimpleResultPromise(scriptState, this); |
654 ScriptPromise promise = result->promise(); | 772 ScriptPromise promise = result->promise(); |
655 | 773 |
656 // 4. Run the following steps asynchronously (documented in | 774 // 4. Run the following steps in parallel (done in closeTask()). |
657 // actionTimerFired()). | |
658 m_pendingActions.append(PendingAction::CreatePendingClose(result)); | 775 m_pendingActions.append(PendingAction::CreatePendingClose(result)); |
659 if (!m_actionTimer.isActive()) | 776 if (!m_actionTimer.isActive()) |
660 m_actionTimer.startOneShot(0, BLINK_FROM_HERE); | 777 m_actionTimer.startOneShot(0, BLINK_FROM_HERE); |
661 | 778 |
662 // 5. Return promise. | 779 // 5. Return promise. |
663 return promise; | 780 return promise; |
664 } | 781 } |
665 | 782 |
| 783 void MediaKeySession::closeTask(ContentDecryptionModuleResult* result) { |
| 784 // NOTE: Continue step 4 of MediaKeySession::close(). |
| 785 DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ")"; |
| 786 |
| 787 // close() in Chromium will execute steps 5.1 through 5.3. |
| 788 m_session->close(result->result()); |
| 789 |
| 790 // Last step (5.3.2 Resolve promise) will be done when |result| is resolved. |
| 791 } |
| 792 |
666 ScriptPromise MediaKeySession::remove(ScriptState* scriptState) { | 793 ScriptPromise MediaKeySession::remove(ScriptState* scriptState) { |
667 DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ")"; | 794 DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ")"; |
668 | 795 |
669 // From https://w3c.github.io/encrypted-media/#remove: | 796 // From https://w3c.github.io/encrypted-media/#remove: |
670 // Removes stored session data associated with this object. When this | 797 // Removes stored session data associated with this object. When this |
671 // method is invoked, the user agent must run the following steps: | 798 // method is invoked, the user agent must run the following steps: |
672 | 799 |
673 // 1. If this object is closed, return a promise rejected with an | 800 // 1. If this object is closed, return a promise rejected with an |
674 // InvalidStateError. | 801 // InvalidStateError. |
675 if (m_isClosed) | 802 if (m_isClosed) |
(...skipping 11 matching lines...) Expand all Loading... |
687 return ScriptPromise::reject( | 814 return ScriptPromise::reject( |
688 scriptState, | 815 scriptState, |
689 V8ThrowException::createTypeError( | 816 V8ThrowException::createTypeError( |
690 scriptState->isolate(), "The session type is not persistent.")); | 817 scriptState->isolate(), "The session type is not persistent.")); |
691 } | 818 } |
692 | 819 |
693 // 4. Let promise be a new promise. | 820 // 4. Let promise be a new promise. |
694 SimpleResultPromise* result = new SimpleResultPromise(scriptState, this); | 821 SimpleResultPromise* result = new SimpleResultPromise(scriptState, this); |
695 ScriptPromise promise = result->promise(); | 822 ScriptPromise promise = result->promise(); |
696 | 823 |
697 // 5. Run the following steps asynchronously (documented in | 824 // 5. Run the following steps asynchronously (done in removeTask()). |
698 // actionTimerFired()). | |
699 m_pendingActions.append(PendingAction::CreatePendingRemove(result)); | 825 m_pendingActions.append(PendingAction::CreatePendingRemove(result)); |
700 if (!m_actionTimer.isActive()) | 826 if (!m_actionTimer.isActive()) |
701 m_actionTimer.startOneShot(0, BLINK_FROM_HERE); | 827 m_actionTimer.startOneShot(0, BLINK_FROM_HERE); |
702 | 828 |
703 // 6. Return promise. | 829 // 6. Return promise. |
704 return promise; | 830 return promise; |
705 } | 831 } |
706 | 832 |
| 833 void MediaKeySession::removeTask(ContentDecryptionModuleResult* result) { |
| 834 // NOTE: Continue step 5 of MediaKeySession::remove(). |
| 835 DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ")"; |
| 836 |
| 837 // remove() in Chromium will execute steps 5.1 through 5.3. |
| 838 m_session->remove(result->result()); |
| 839 |
| 840 // Last step (5.3.6 Resolve promise) will be done when |result| is resolved. |
| 841 } |
| 842 |
707 void MediaKeySession::actionTimerFired(TimerBase*) { | 843 void MediaKeySession::actionTimerFired(TimerBase*) { |
708 DCHECK(m_pendingActions.size()); | 844 DCHECK(m_pendingActions.size()); |
709 | 845 |
710 // Resolving promises now run synchronously and may result in additional | 846 // Resolving promises now run synchronously and may result in additional |
711 // actions getting added to the queue. As a result, swap the queue to | 847 // actions getting added to the queue. As a result, swap the queue to |
712 // a local copy to avoid problems if this happens. | 848 // a local copy to avoid problems if this happens. |
713 HeapDeque<Member<PendingAction>> pendingActions; | 849 HeapDeque<Member<PendingAction>> pendingActions; |
714 pendingActions.swap(m_pendingActions); | 850 pendingActions.swap(m_pendingActions); |
715 | 851 |
716 while (!pendingActions.isEmpty()) { | 852 while (!pendingActions.isEmpty()) { |
717 PendingAction* action = pendingActions.takeFirst(); | 853 PendingAction* action = pendingActions.takeFirst(); |
718 | 854 |
719 switch (action->getType()) { | 855 switch (action->getType()) { |
720 case PendingAction::GenerateRequest: | 856 case PendingAction::GenerateRequest: |
721 // NOTE: Continue step 10 of MediaKeySession::generateRequest(). | 857 generateRequestTask(action->result(), action->initDataType(), |
722 DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this | 858 action->data()); |
723 << ") GenerateRequest"; | |
724 | |
725 // initializeNewSession() in Chromium will execute steps 10.1 to 10.9. | |
726 m_session->initializeNewSession( | |
727 action->initDataType(), | |
728 static_cast<unsigned char*>(action->data()->data()), | |
729 action->data()->byteLength(), m_sessionType, | |
730 action->result()->result()); | |
731 | |
732 // Remaining steps (from 10.10) executed in finishGenerateRequest(), | |
733 // called when |result| is resolved. | |
734 break; | 859 break; |
735 | 860 |
736 case PendingAction::Load: | 861 case PendingAction::Load: |
737 // NOTE: Continue step 8 of MediaKeySession::load(). | 862 loadTask(action->result(), action->sessionId()); |
738 DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this | |
739 << ") Load"; | |
740 | |
741 // 8.1 Let sanitized session ID be a validated and/or sanitized | |
742 // version of sessionId. The user agent should thoroughly | |
743 // validate the sessionId value before passing it to the CDM. | |
744 // At a minimum, this should include checking that the length | |
745 // and value (e.g. alphanumeric) are reasonable. | |
746 // 8.2 If the preceding step failed, or if sanitized session ID | |
747 // is empty, reject promise with a newly created TypeError. | |
748 if (!isValidSessionId(action->sessionId())) { | |
749 action->result()->completeWithError( | |
750 WebContentDecryptionModuleExceptionTypeError, 0, | |
751 "Invalid sessionId"); | |
752 return; | |
753 } | |
754 | |
755 // 8.3 If there is an unclosed session in the object's Document | |
756 // whose sessionId attribute is sanitized session ID, reject | |
757 // promise with a new DOMException whose name is | |
758 // QuotaExceededError. In other words, do not create a session | |
759 // if a non-closed session, regardless of type, already exists | |
760 // for this sanitized session ID in this browsing context. | |
761 // (Done in the CDM.) | |
762 | |
763 // 8.4 Let expiration time be NaN. | |
764 // (Done in the constructor.) | |
765 DCHECK(std::isnan(m_expiration)); | |
766 | |
767 // load() in Chromium will execute steps 8.5 through 8.8. | |
768 m_session->load(action->sessionId(), action->result()->result()); | |
769 | |
770 // Remaining steps (from 8.9) executed in finishLoad(), called | |
771 // when |result| is resolved. | |
772 break; | 863 break; |
773 | 864 |
774 case PendingAction::Update: | 865 case PendingAction::Update: |
775 // NOTE: Continue step 5 of MediaKeySession::update(). | 866 updateTask(action->result(), action->data()); |
776 DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this | |
777 << ") Update"; | |
778 | |
779 // update() in Chromium will execute steps 5.1 through 5.8. | |
780 m_session->update(static_cast<unsigned char*>(action->data()->data()), | |
781 action->data()->byteLength(), | |
782 action->result()->result()); | |
783 | |
784 // Last step (5.9 Resolve promise) will be done when |result| is | |
785 // resolved. | |
786 break; | 867 break; |
787 | 868 |
788 case PendingAction::Close: | 869 case PendingAction::Close: |
789 // NOTE: Continue step 4 of MediaKeySession::close(). | 870 closeTask(action->result()); |
790 DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this | |
791 << ") Close"; | |
792 | |
793 // close() in Chromium will execute steps 4.1 through 4.2. | |
794 m_session->close(action->result()->result()); | |
795 | |
796 // Last step (4.3 Resolve promise) will be done when |result| is | |
797 // resolved. | |
798 break; | 871 break; |
799 | 872 |
800 case PendingAction::Remove: | 873 case PendingAction::Remove: |
801 // NOTE: Continue step 5 of MediaKeySession::remove(). | 874 removeTask(action->result()); |
802 DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this | |
803 << ") Remove"; | |
804 | |
805 // remove() in Chromium will execute steps 5.1 through 5.3. | |
806 m_session->remove(action->result()->result()); | |
807 | |
808 // Last step (5.3.3 Resolve promise) will be done when |result| is | |
809 // resolved. | |
810 break; | 875 break; |
811 } | 876 } |
812 } | 877 } |
813 } | 878 } |
814 | 879 |
815 void MediaKeySession::finishGenerateRequest() { | |
816 // 9.8 If any of the preceding steps failed, reject promise with a | |
817 // new DOMException whose name is the appropriate error name. | |
818 // (Done by CDM calling result.completeWithError() as appropriate.) | |
819 | |
820 // 9.9 Set the sessionId attribute to session id. | |
821 DCHECK(!sessionId().isEmpty()); | |
822 | |
823 // 9.10 Let this object's callable be true. | |
824 m_isCallable = true; | |
825 | |
826 // 9.11 Run the queue a "message" event algorithm on the session, | |
827 // providing "license-request" and message. | |
828 // (Done by the CDM.) | |
829 | |
830 // 9.12 Resolve promise. | |
831 // (Done by NewSessionResultPromise.) | |
832 } | |
833 | |
834 void MediaKeySession::finishLoad() { | |
835 // 8.9 If any of the preceding steps failed, reject promise with a new | |
836 // DOMException whose name is the appropriate error name. | |
837 // (Done by CDM calling result.completeWithError() as appropriate.) | |
838 | |
839 // 8.10 Set the sessionId attribute to sanitized session ID. | |
840 DCHECK(!sessionId().isEmpty()); | |
841 | |
842 // 8.11 Let this object's callable be true. | |
843 m_isCallable = true; | |
844 | |
845 // 8.12 If the loaded session contains information about any keys (there | |
846 // are known keys), run the update key statuses algorithm on the | |
847 // session, providing each key's key ID along with the appropriate | |
848 // MediaKeyStatus. Should additional processing be necessary to | |
849 // determine with certainty the status of a key, use the non-"usable" | |
850 // MediaKeyStatus value that corresponds to the reason for the | |
851 // additional processing. Once the additional processing for one or | |
852 // more keys has completed, run the update key statuses algorithm | |
853 // again if any of the statuses has changed. | |
854 // (Done by the CDM.) | |
855 | |
856 // 8.13 Run the Update Expiration algorithm on the session, | |
857 // providing expiration time. | |
858 // (Done by the CDM.) | |
859 | |
860 // 8.14 If message is not null, run the queue a "message" event algorithm | |
861 // on the session, providing message type and message. | |
862 // (Done by the CDM.) | |
863 | |
864 // 8.15 Resolve promise with true. | |
865 // (Done by LoadSessionResultPromise.) | |
866 } | |
867 | |
868 // Queue a task to fire a simple event named keymessage at the new object. | 880 // Queue a task to fire a simple event named keymessage at the new object. |
869 void MediaKeySession::message(MessageType messageType, | 881 void MediaKeySession::message(MessageType messageType, |
870 const unsigned char* message, | 882 const unsigned char* message, |
871 size_t messageLength) { | 883 size_t messageLength) { |
872 DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ")"; | 884 DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ")"; |
873 | 885 |
874 // Verify that 'message' not fired before session initialization is complete. | 886 // Verify that 'message' not fired before session initialization is complete. |
875 DCHECK(m_isCallable); | 887 DCHECK(m_isCallable); |
876 | 888 |
877 // From https://w3c.github.io/encrypted-media/#queue-message: | 889 // From https://w3c.github.io/encrypted-media/#queue-message: |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1033 visitor->trace(m_asyncEventQueue); | 1045 visitor->trace(m_asyncEventQueue); |
1034 visitor->trace(m_pendingActions); | 1046 visitor->trace(m_pendingActions); |
1035 visitor->trace(m_mediaKeys); | 1047 visitor->trace(m_mediaKeys); |
1036 visitor->trace(m_keyStatusesMap); | 1048 visitor->trace(m_keyStatusesMap); |
1037 visitor->trace(m_closedPromise); | 1049 visitor->trace(m_closedPromise); |
1038 EventTargetWithInlineData::trace(visitor); | 1050 EventTargetWithInlineData::trace(visitor); |
1039 ActiveDOMObject::trace(visitor); | 1051 ActiveDOMObject::trace(visitor); |
1040 } | 1052 } |
1041 | 1053 |
1042 } // namespace blink | 1054 } // namespace blink |
OLD | NEW |