Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(319)

Side by Side Diff: third_party/WebKit/Source/modules/encryptedmedia/MediaKeySession.cpp

Issue 2342953002: Update EME errors to use TypeError (Closed)
Patch Set: createDOMException Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 11 matching lines...) Expand all
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE. 23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */ 24 */
25 25
26 #include "modules/encryptedmedia/MediaKeySession.h" 26 #include "modules/encryptedmedia/MediaKeySession.h"
27 27
28 #include "bindings/core/v8/DOMWrapperWorld.h" 28 #include "bindings/core/v8/DOMWrapperWorld.h"
29 #include "bindings/core/v8/ScriptPromise.h" 29 #include "bindings/core/v8/ScriptPromise.h"
30 #include "bindings/core/v8/ScriptPromiseResolver.h" 30 #include "bindings/core/v8/ScriptPromiseResolver.h"
31 #include "bindings/core/v8/ScriptState.h" 31 #include "bindings/core/v8/ScriptState.h"
32 #include "bindings/core/v8/V8ThrowException.h"
32 #include "core/dom/DOMArrayBuffer.h" 33 #include "core/dom/DOMArrayBuffer.h"
33 #include "core/dom/DOMException.h" 34 #include "core/dom/DOMException.h"
34 #include "core/dom/ExceptionCode.h" 35 #include "core/dom/ExceptionCode.h"
35 #include "core/events/Event.h" 36 #include "core/events/Event.h"
36 #include "core/events/GenericEventQueue.h" 37 #include "core/events/GenericEventQueue.h"
37 #include "modules/encryptedmedia/ContentDecryptionModuleResultPromise.h" 38 #include "modules/encryptedmedia/ContentDecryptionModuleResultPromise.h"
38 #include "modules/encryptedmedia/EncryptedMediaUtils.h" 39 #include "modules/encryptedmedia/EncryptedMediaUtils.h"
39 #include "modules/encryptedmedia/MediaKeyMessageEvent.h" 40 #include "modules/encryptedmedia/MediaKeyMessageEvent.h"
40 #include "modules/encryptedmedia/MediaKeys.h" 41 #include "modules/encryptedmedia/MediaKeys.h"
41 #include "platform/ContentDecryptionModuleResult.h" 42 #include "platform/ContentDecryptionModuleResult.h"
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 75
75 // Check that the sessionId only contains alphanumeric characters. 76 // Check that the sessionId only contains alphanumeric characters.
76 for (unsigned i = 0; i < sessionId.length(); ++i) { 77 for (unsigned i = 0; i < sessionId.length(); ++i) {
77 if (!isASCIIAlphanumeric(sessionId[i])) 78 if (!isASCIIAlphanumeric(sessionId[i]))
78 return false; 79 return false;
79 } 80 }
80 81
81 return true; 82 return true;
82 } 83 }
83 84
85 static bool IsPersistentSessionType(WebEncryptedMediaSessionType sessionType) {
xhwang 2016/10/17 23:13:55 Add a comment that this implements "5.1.1 Is persi
jrummell 2016/10/18 00:50:39 Done.
86 switch (sessionType) {
87 case WebEncryptedMediaSessionType::Temporary:
88 return false;
89 case WebEncryptedMediaSessionType::PersistentLicense:
90 return true;
91 case WebEncryptedMediaSessionType::PersistentReleaseMessage:
92 return true;
93 case blink::WebEncryptedMediaSessionType::Unknown:
94 break;
95 }
96
97 NOTREACHED();
98 return false;
99 }
100
84 static String ConvertKeyStatusToString( 101 static String ConvertKeyStatusToString(
85 const WebEncryptedMediaKeyInformation::KeyStatus status) { 102 const WebEncryptedMediaKeyInformation::KeyStatus status) {
86 switch (status) { 103 switch (status) {
87 case WebEncryptedMediaKeyInformation::KeyStatus::Usable: 104 case WebEncryptedMediaKeyInformation::KeyStatus::Usable:
88 return "usable"; 105 return "usable";
89 case WebEncryptedMediaKeyInformation::KeyStatus::Expired: 106 case WebEncryptedMediaKeyInformation::KeyStatus::Expired:
90 return "expired"; 107 return "expired";
91 case WebEncryptedMediaKeyInformation::KeyStatus::Released: 108 case WebEncryptedMediaKeyInformation::KeyStatus::Released:
92 return "released"; 109 return "released";
93 case WebEncryptedMediaKeyInformation::KeyStatus::OutputRestricted: 110 case WebEncryptedMediaKeyInformation::KeyStatus::OutputRestricted:
(...skipping 10 matching lines...) Expand all
104 return "internal-error"; 121 return "internal-error";
105 } 122 }
106 123
107 static ScriptPromise CreateRejectedPromiseNotCallable( 124 static ScriptPromise CreateRejectedPromiseNotCallable(
108 ScriptState* scriptState) { 125 ScriptState* scriptState) {
109 return ScriptPromise::rejectWithDOMException( 126 return ScriptPromise::rejectWithDOMException(
110 scriptState, 127 scriptState,
111 DOMException::create(InvalidStateError, "The session is not callable.")); 128 DOMException::create(InvalidStateError, "The session is not callable."));
112 } 129 }
113 130
131 static ScriptPromise CreateRejectedPromiseAlreadyClosed(
132 ScriptState* scriptState) {
133 return ScriptPromise::rejectWithDOMException(
134 scriptState, DOMException::create(InvalidStateError,
135 "The session is already closed."));
136 }
137
114 static ScriptPromise CreateRejectedPromiseAlreadyInitialized( 138 static ScriptPromise CreateRejectedPromiseAlreadyInitialized(
115 ScriptState* scriptState) { 139 ScriptState* scriptState) {
116 return ScriptPromise::rejectWithDOMException( 140 return ScriptPromise::rejectWithDOMException(
117 scriptState, DOMException::create(InvalidStateError, 141 scriptState, DOMException::create(InvalidStateError,
118 "The session is already initialized.")); 142 "The session is already initialized."));
119 } 143 }
120 144
121 // A class holding a pending action. 145 // A class holding a pending action.
122 class MediaKeySession::PendingAction 146 class MediaKeySession::PendingAction
123 : public GarbageCollectedFinalized<MediaKeySession::PendingAction> { 147 : public GarbageCollectedFinalized<MediaKeySession::PendingAction> {
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 ScriptPromise MediaKeySession::generateRequest(ScriptState* scriptState, 444 ScriptPromise MediaKeySession::generateRequest(ScriptState* scriptState,
421 const String& initDataTypeString, 445 const String& initDataTypeString,
422 const DOMArrayPiece& initData) { 446 const DOMArrayPiece& initData) {
423 DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ") " 447 DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ") "
424 << initDataTypeString; 448 << initDataTypeString;
425 449
426 // From https://w3c.github.io/encrypted-media/#generateRequest: 450 // From https://w3c.github.io/encrypted-media/#generateRequest:
427 // Generates a request based on the initData. When this method is invoked, 451 // Generates a request based on the initData. When this method is invoked,
428 // the user agent must run the following steps: 452 // the user agent must run the following steps:
429 453
430 // 1. If this object's uninitialized value is false, return a promise 454 // 1. If this object is closed, return a promise rejected with an
431 // rejected with a new DOMException whose name is "InvalidStateError". 455 // InvalidStateError.
456 if (m_isClosed)
457 return CreateRejectedPromiseAlreadyClosed(scriptState);
458
459 // 2. If this object's uninitialized value is false, return a promise
460 // rejected with an InvalidStateError.
432 if (!m_isUninitialized) 461 if (!m_isUninitialized)
433 return CreateRejectedPromiseAlreadyInitialized(scriptState); 462 return CreateRejectedPromiseAlreadyInitialized(scriptState);
434 463
435 // 2. Let this object's uninitialized be false. 464 // 3. Let this object's uninitialized be false.
436 m_isUninitialized = false; 465 m_isUninitialized = false;
437 466
438 // 3. If initDataType is an empty string, return a promise rejected with a 467 // 4. If initDataType is the empty string, return a promise rejected
439 // new DOMException whose name is "InvalidAccessError". 468 // with a newly created TypeError.
440 if (initDataTypeString.isEmpty()) { 469 if (initDataTypeString.isEmpty()) {
441 return ScriptPromise::rejectWithDOMException( 470 return ScriptPromise::reject(
442 scriptState, 471 scriptState,
443 DOMException::create(InvalidAccessError, 472 V8ThrowException::createTypeError(
444 "The initDataType parameter is empty.")); 473 scriptState->isolate(), "The initDataType parameter is empty."));
445 } 474 }
446 475
447 // 4. If initData is an empty array, return a promise rejected with a new 476 // 5. If initData is an empty array, return a promise rejected with a
448 // DOMException whose name is"InvalidAccessError". 477 // newly created TypeError.
449 if (!initData.byteLength()) { 478 if (!initData.byteLength()) {
450 return ScriptPromise::rejectWithDOMException( 479 return ScriptPromise::reject(
451 scriptState, DOMException::create(InvalidAccessError, 480 scriptState,
481 V8ThrowException::createTypeError(scriptState->isolate(),
452 "The initData parameter is empty.")); 482 "The initData parameter is empty."));
453 } 483 }
454 484
455 // 5. If the Key System implementation represented by this object's cdm 485 // 6. If the Key System implementation represented by this object's cdm
456 // implementation value does not support initDataType as an 486 // implementation value does not support initDataType as an
457 // Initialization Data Type, return a promise rejected with a new 487 // Initialization Data Type, return a promise rejected with a new
458 // DOMException whose name is NotSupportedError. String comparison 488 // DOMException whose name is NotSupportedError. String comparison
459 // is case-sensitive. 489 // is case-sensitive.
460 // (blink side doesn't know what the CDM supports, so the proper check 490 // (blink side doesn't know what the CDM supports, so the proper check
461 // will be done on the Chromium side. However, we can verify that 491 // will be done on the Chromium side. However, we can verify that
462 // |initDataType| is one of the registered values.) 492 // |initDataType| is one of the registered values.)
463 WebEncryptedMediaInitDataType initDataType = 493 WebEncryptedMediaInitDataType initDataType =
464 EncryptedMediaUtils::convertToInitDataType(initDataTypeString); 494 EncryptedMediaUtils::convertToInitDataType(initDataTypeString);
465 if (initDataType == WebEncryptedMediaInitDataType::Unknown) { 495 if (initDataType == WebEncryptedMediaInitDataType::Unknown) {
466 return ScriptPromise::rejectWithDOMException( 496 return ScriptPromise::rejectWithDOMException(
467 scriptState, 497 scriptState,
468 DOMException::create(NotSupportedError, 498 DOMException::create(NotSupportedError,
469 "The initialization data type '" + 499 "The initialization data type '" +
470 initDataTypeString + "' is not supported.")); 500 initDataTypeString + "' is not supported."));
471 } 501 }
472 502
473 // 6. Let init data be a copy of the contents of the initData parameter. 503 // 7. Let init data be a copy of the contents of the initData parameter.
474 DOMArrayBuffer* initDataBuffer = 504 DOMArrayBuffer* initDataBuffer =
475 DOMArrayBuffer::create(initData.data(), initData.byteLength()); 505 DOMArrayBuffer::create(initData.data(), initData.byteLength());
476 506
477 // 7. Let session type be this object's session type. 507 // 8. Let session type be this object's session type.
478 // (Done in constructor.) 508 // (Done in constructor.)
479 509
480 // 8. Let promise be a new promise. 510 // 9. Let promise be a new promise.
481 NewSessionResultPromise* result = 511 NewSessionResultPromise* result =
482 new NewSessionResultPromise(scriptState, this); 512 new NewSessionResultPromise(scriptState, this);
483 ScriptPromise promise = result->promise(); 513 ScriptPromise promise = result->promise();
484 514
485 // 9. Run the following steps asynchronously (documented in 515 // 10. Run the following steps asynchronously (documented in
486 // actionTimerFired()) 516 // actionTimerFired())
487 m_pendingActions.append(PendingAction::CreatePendingGenerateRequest( 517 m_pendingActions.append(PendingAction::CreatePendingGenerateRequest(
488 result, initDataType, initDataBuffer)); 518 result, initDataType, initDataBuffer));
489 DCHECK(!m_actionTimer.isActive()); 519 DCHECK(!m_actionTimer.isActive());
490 m_actionTimer.startOneShot(0, BLINK_FROM_HERE); 520 m_actionTimer.startOneShot(0, BLINK_FROM_HERE);
491 521
492 // 10. Return promise. 522 // 11. Return promise.
493 return promise; 523 return promise;
494 } 524 }
495 525
496 ScriptPromise MediaKeySession::load(ScriptState* scriptState, 526 ScriptPromise MediaKeySession::load(ScriptState* scriptState,
497 const String& sessionId) { 527 const String& sessionId) {
498 DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ") " 528 DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ") "
499 << sessionId; 529 << sessionId;
500 530
501 // From https://w3c.github.io/encrypted-media/#load: 531 // From https://w3c.github.io/encrypted-media/#load:
502 // Loads the data stored for the specified session into this object. When 532 // Loads the data stored for the specified session into this object. When
503 // this method is invoked, the user agent must run the following steps: 533 // this method is invoked, the user agent must run the following steps:
504 534
505 // 1. If this object's uninitialized value is false, return a promise 535 // 1. If this object is closed, return a promise rejected with an
506 // rejected with a new DOMException whose name is "InvalidStateError". 536 // InvalidStateError.
537 if (m_isClosed)
538 return CreateRejectedPromiseAlreadyClosed(scriptState);
539
540 // 2. If this object's uninitialized value is false, return a promise
541 // rejected with an InvalidStateError.
507 if (!m_isUninitialized) 542 if (!m_isUninitialized)
508 return CreateRejectedPromiseAlreadyInitialized(scriptState); 543 return CreateRejectedPromiseAlreadyInitialized(scriptState);
509 544
510 // 2. Let this object's uninitialized be false. 545 // 3. Let this object's uninitialized value be false.
511 m_isUninitialized = false; 546 m_isUninitialized = false;
512 547
513 // 3. If sessionId is an empty string, return a promise rejected with a 548 // 4. If sessionId is the empty string, return a promise rejected with
514 // new DOMException whose name is "InvalidAccessError". 549 // a newly created TypeError.
515 if (sessionId.isEmpty()) { 550 if (sessionId.isEmpty()) {
516 return ScriptPromise::rejectWithDOMException( 551 return ScriptPromise::reject(
517 scriptState, DOMException::create(InvalidAccessError, 552 scriptState,
553 V8ThrowException::createTypeError(scriptState->isolate(),
518 "The sessionId parameter is empty.")); 554 "The sessionId parameter is empty."));
519 } 555 }
520 556
521 // 4. If this object's session type is not "persistent-license" or 557 // 5. If the result of running the "Is persistent session type?" algorithm
522 // "persistent-release-message", return a promise rejected with a 558 // on this object's session type is false, return a promise rejected
523 // new DOMException whose name is InvalidAccessError. 559 // with a newly created TypeError.
524 if (m_sessionType != WebEncryptedMediaSessionType::PersistentLicense && 560 if (!IsPersistentSessionType(m_sessionType)) {
525 m_sessionType != WebEncryptedMediaSessionType::PersistentReleaseMessage) { 561 return ScriptPromise::reject(
526 return ScriptPromise::rejectWithDOMException(
527 scriptState, 562 scriptState,
528 DOMException::create(InvalidAccessError, 563 V8ThrowException::createTypeError(
529 "The session type is not persistent.")); 564 scriptState->isolate(), "The session type is not persistent."));
530 } 565 }
531 566
532 // 5. If the Key System implementation represented by this object's cdm
533 // implementation value does not support loading previous sessions,
534 // return a promise rejected with a new DOMException whose name is
535 // NotSupportedError.
536 // FIXME: Implement this (http://crbug.com/448922).
537
538 // 6. Let origin be the origin of this object's Document. 567 // 6. Let origin be the origin of this object's Document.
539 // (Available as getExecutionContext()->getSecurityOrigin() anytime.) 568 // (Available as getExecutionContext()->getSecurityOrigin() anytime.)
540 569
541 // 7. Let promise be a new promise. 570 // 7. Let promise be a new promise.
542 LoadSessionResultPromise* result = 571 LoadSessionResultPromise* result =
543 new LoadSessionResultPromise(scriptState, this); 572 new LoadSessionResultPromise(scriptState, this);
544 ScriptPromise promise = result->promise(); 573 ScriptPromise promise = result->promise();
545 574
546 // 8. Run the following steps asynchronously (documented in 575 // 8. Run the following steps asynchronously (documented in
547 // actionTimerFired()) 576 // actionTimerFired())
548 m_pendingActions.append( 577 m_pendingActions.append(
549 PendingAction::CreatePendingLoadRequest(result, sessionId)); 578 PendingAction::CreatePendingLoadRequest(result, sessionId));
550 DCHECK(!m_actionTimer.isActive()); 579 DCHECK(!m_actionTimer.isActive());
551 m_actionTimer.startOneShot(0, BLINK_FROM_HERE); 580 m_actionTimer.startOneShot(0, BLINK_FROM_HERE);
552 581
553 // 9. Return promise. 582 // 9. Return promise.
554 return promise; 583 return promise;
555 } 584 }
556 585
557 ScriptPromise MediaKeySession::update(ScriptState* scriptState, 586 ScriptPromise MediaKeySession::update(ScriptState* scriptState,
558 const DOMArrayPiece& response) { 587 const DOMArrayPiece& response) {
559 DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ")"; 588 DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ")";
560 DCHECK(!m_isClosed);
561 589
562 // From https://w3c.github.io/encrypted-media/#update: 590 // From https://w3c.github.io/encrypted-media/#update:
563 // Provides messages, including licenses, to the CDM. When this method is 591 // Provides messages, including licenses, to the CDM. When this method is
564 // invoked, the user agent must run the following steps: 592 // invoked, the user agent must run the following steps:
565 593
566 // 1. If this object's callable value is false, return a promise rejected 594 // 1. If this object is closed, return a promise rejected with an
567 // with a new DOMException whose name is InvalidStateError. 595 // InvalidStateError.
596 if (m_isClosed)
597 return CreateRejectedPromiseAlreadyClosed(scriptState);
598
599 // 2. If this object's callable value is false, return a promise
600 // rejected with an InvalidStateError.
568 if (!m_isCallable) 601 if (!m_isCallable)
569 return CreateRejectedPromiseNotCallable(scriptState); 602 return CreateRejectedPromiseNotCallable(scriptState);
570 603
571 // 2. If response is an empty array, return a promise rejected with a 604 // 3. If response is an empty array, return a promise rejected with a
572 // new DOMException whose name is InvalidAccessError. 605 // newly created TypeError.
573 if (!response.byteLength()) { 606 if (!response.byteLength()) {
574 return ScriptPromise::rejectWithDOMException( 607 return ScriptPromise::reject(
575 scriptState, DOMException::create(InvalidAccessError, 608 scriptState,
609 V8ThrowException::createTypeError(scriptState->isolate(),
576 "The response parameter is empty.")); 610 "The response parameter is empty."));
577 } 611 }
578 612
579 // 3. Let response copy be a copy of the contents of the response parameter. 613 // 4. Let response copy be a copy of the contents of the response parameter.
580 DOMArrayBuffer* responseCopy = 614 DOMArrayBuffer* responseCopy =
581 DOMArrayBuffer::create(response.data(), response.byteLength()); 615 DOMArrayBuffer::create(response.data(), response.byteLength());
582 616
583 // 4. Let promise be a new promise. 617 // 5. Let promise be a new promise.
584 SimpleResultPromise* result = new SimpleResultPromise(scriptState, this); 618 SimpleResultPromise* result = new SimpleResultPromise(scriptState, this);
585 ScriptPromise promise = result->promise(); 619 ScriptPromise promise = result->promise();
586 620
587 // 5. Run the following steps asynchronously (documented in 621 // 6. Run the following steps asynchronously (documented in
588 // actionTimerFired()) 622 // actionTimerFired())
589 m_pendingActions.append( 623 m_pendingActions.append(
590 PendingAction::CreatePendingUpdate(result, responseCopy)); 624 PendingAction::CreatePendingUpdate(result, responseCopy));
591 if (!m_actionTimer.isActive()) 625 if (!m_actionTimer.isActive())
592 m_actionTimer.startOneShot(0, BLINK_FROM_HERE); 626 m_actionTimer.startOneShot(0, BLINK_FROM_HERE);
593 627
594 // 6. Return promise. 628 // 7. Return promise.
595 return promise; 629 return promise;
596 } 630 }
597 631
598 ScriptPromise MediaKeySession::close(ScriptState* scriptState) { 632 ScriptPromise MediaKeySession::close(ScriptState* scriptState) {
599 DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ")"; 633 DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ")";
600 634
601 // From https://w3c.github.io/encrypted-media/#close: 635 // From https://w3c.github.io/encrypted-media/#close:
602 // Indicates that the application no longer needs the session and the CDM 636 // Indicates that the application no longer needs the session and the CDM
603 // should release any resources associated with this object and close it. 637 // should release any resources associated with this object and close it.
604 // When this method is invoked, the user agent must run the following steps: 638 // When this method is invoked, the user agent must run the following steps:
(...skipping 22 matching lines...) Expand all
627 return promise; 661 return promise;
628 } 662 }
629 663
630 ScriptPromise MediaKeySession::remove(ScriptState* scriptState) { 664 ScriptPromise MediaKeySession::remove(ScriptState* scriptState) {
631 DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ")"; 665 DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this << ")";
632 666
633 // From https://w3c.github.io/encrypted-media/#remove: 667 // From https://w3c.github.io/encrypted-media/#remove:
634 // Removes stored session data associated with this object. When this 668 // Removes stored session data associated with this object. When this
635 // method is invoked, the user agent must run the following steps: 669 // method is invoked, the user agent must run the following steps:
636 670
637 // 1. If this object's callable value is false, return a promise rejected 671 // 1. If this object is closed, return a promise rejected with an
638 // with a new DOMException whose name is "InvalidStateError". 672 // InvalidStateError.
673 if (m_isClosed)
674 return CreateRejectedPromiseAlreadyClosed(scriptState);
675
676 // 2. If this object's callable value is false, return a promise rejected
677 // with an InvalidStateError.
639 if (!m_isCallable) 678 if (!m_isCallable)
640 return CreateRejectedPromiseNotCallable(scriptState); 679 return CreateRejectedPromiseNotCallable(scriptState);
641 680
642 // 2. If this object's session type is not "persistent-license" or 681 // 3. If the result of running the "Is persistent session type?" algorithm
643 // "persistent-release-message", return a promise rejected with a 682 // on this object's session type is false, return a promise rejected
644 // new DOMException whose name is InvalidAccessError. 683 // with a newly created TypeError.
645 if (m_sessionType != WebEncryptedMediaSessionType::PersistentLicense && 684 if (!IsPersistentSessionType(m_sessionType)) {
646 m_sessionType != WebEncryptedMediaSessionType::PersistentReleaseMessage) { 685 return ScriptPromise::reject(
647 return ScriptPromise::rejectWithDOMException(
648 scriptState, 686 scriptState,
649 DOMException::create(InvalidAccessError, 687 V8ThrowException::createTypeError(
650 "The session type is not persistent.")); 688 scriptState->isolate(), "The session type is not persistent."));
651 }
652
653 // 3. If the Session Close algorithm has been run on this object, return a
654 // promise rejected with a new DOMException whose name is
655 // "InvalidStateError".
656 if (m_isClosed) {
657 return ScriptPromise::rejectWithDOMException(
658 scriptState, DOMException::create(InvalidStateError,
659 "The session is already closed."));
660 } 689 }
661 690
662 // 4. Let promise be a new promise. 691 // 4. Let promise be a new promise.
663 SimpleResultPromise* result = new SimpleResultPromise(scriptState, this); 692 SimpleResultPromise* result = new SimpleResultPromise(scriptState, this);
664 ScriptPromise promise = result->promise(); 693 ScriptPromise promise = result->promise();
665 694
666 // 5. Run the following steps asynchronously (documented in 695 // 5. Run the following steps asynchronously (documented in
667 // actionTimerFired()). 696 // actionTimerFired()).
668 m_pendingActions.append(PendingAction::CreatePendingRemove(result)); 697 m_pendingActions.append(PendingAction::CreatePendingRemove(result));
669 if (!m_actionTimer.isActive()) 698 if (!m_actionTimer.isActive())
670 m_actionTimer.startOneShot(0, BLINK_FROM_HERE); 699 m_actionTimer.startOneShot(0, BLINK_FROM_HERE);
671 700
672 // 6. Return promise. 701 // 6. Return promise.
673 return promise; 702 return promise;
674 } 703 }
675 704
676 void MediaKeySession::actionTimerFired(TimerBase*) { 705 void MediaKeySession::actionTimerFired(TimerBase*) {
677 DCHECK(m_pendingActions.size()); 706 DCHECK(m_pendingActions.size());
678 707
679 // Resolving promises now run synchronously and may result in additional 708 // Resolving promises now run synchronously and may result in additional
680 // actions getting added to the queue. As a result, swap the queue to 709 // actions getting added to the queue. As a result, swap the queue to
681 // a local copy to avoid problems if this happens. 710 // a local copy to avoid problems if this happens.
682 HeapDeque<Member<PendingAction>> pendingActions; 711 HeapDeque<Member<PendingAction>> pendingActions;
683 pendingActions.swap(m_pendingActions); 712 pendingActions.swap(m_pendingActions);
684 713
685 while (!pendingActions.isEmpty()) { 714 while (!pendingActions.isEmpty()) {
686 PendingAction* action = pendingActions.takeFirst(); 715 PendingAction* action = pendingActions.takeFirst();
687 716
688 switch (action->getType()) { 717 switch (action->getType()) {
689 case PendingAction::GenerateRequest: 718 case PendingAction::GenerateRequest:
xhwang 2016/10/17 23:13:55 nit: Not related to this CL. I wonder whether we s
jrummell 2016/10/18 00:50:39 Good idea. Next CL.
690 // NOTE: Continue step 9 of MediaKeySession::generateRequest(). 719 // NOTE: Continue step 10 of MediaKeySession::generateRequest().
691 DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this 720 DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this
692 << ") GenerateRequest"; 721 << ") GenerateRequest";
693 722
694 // initializeNewSession() in Chromium will execute steps 9.1 to 9.7. 723 // initializeNewSession() in Chromium will execute steps 10.1 to 10.9.
695 m_session->initializeNewSession( 724 m_session->initializeNewSession(
696 action->initDataType(), 725 action->initDataType(),
697 static_cast<unsigned char*>(action->data()->data()), 726 static_cast<unsigned char*>(action->data()->data()),
698 action->data()->byteLength(), m_sessionType, 727 action->data()->byteLength(), m_sessionType,
699 action->result()->result()); 728 action->result()->result());
700 729
701 // Remaining steps (from 9.8) executed in finishGenerateRequest(), 730 // Remaining steps (from 10.10) executed in finishGenerateRequest(),
702 // called when |result| is resolved. 731 // called when |result| is resolved.
703 break; 732 break;
704 733
705 case PendingAction::Load: 734 case PendingAction::Load:
706 // NOTE: Continue step 8 of MediaKeySession::load(). 735 // NOTE: Continue step 8 of MediaKeySession::load().
707 DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this 736 DVLOG(MEDIA_KEY_SESSION_LOG_LEVEL) << __func__ << "(" << this
708 << ") Load"; 737 << ") Load";
709 738
710 // 8.1 Let sanitized session ID be a validated and/or sanitized 739 // 8.1 Let sanitized session ID be a validated and/or sanitized
711 // version of sessionId. The user agent should thoroughly 740 // version of sessionId. The user agent should thoroughly
712 // validate the sessionId value before passing it to the CDM. 741 // validate the sessionId value before passing it to the CDM.
713 // At a minimum, this should include checking that the length 742 // At a minimum, this should include checking that the length
714 // and value (e.g. alphanumeric) are reasonable. 743 // and value (e.g. alphanumeric) are reasonable.
715 // 8.2 If the previous step failed, reject promise with a new 744 // 8.2 If the preceding step failed, or if sanitized session ID
716 // DOMException whose name is "InvalidAccessError". 745 // is empty, reject promise with a newly created TypeError.
717 if (!isValidSessionId(action->sessionId())) { 746 if (!isValidSessionId(action->sessionId())) {
718 action->result()->completeWithError( 747 action->result()->completeWithError(
719 WebContentDecryptionModuleExceptionInvalidAccessError, 0, 748 WebContentDecryptionModuleExceptionTypeError, 0,
720 "Invalid sessionId"); 749 "Invalid sessionId");
721 return; 750 return;
722 } 751 }
723 752
724 // 8.3 If there is an unclosed session in the object's Document 753 // 8.3 If there is an unclosed session in the object's Document
725 // whose sessionId attribute is sanitized session ID, reject 754 // whose sessionId attribute is sanitized session ID, reject
726 // promise with a new DOMException whose name is 755 // promise with a new DOMException whose name is
727 // QuotaExceededError. In other words, do not create a session 756 // QuotaExceededError. In other words, do not create a session
728 // if a non-closed session, regardless of type, already exists 757 // if a non-closed session, regardless of type, already exists
729 // for this sanitized session ID in this browsing context. 758 // for this sanitized session ID in this browsing context.
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after
1002 visitor->trace(m_asyncEventQueue); 1031 visitor->trace(m_asyncEventQueue);
1003 visitor->trace(m_pendingActions); 1032 visitor->trace(m_pendingActions);
1004 visitor->trace(m_mediaKeys); 1033 visitor->trace(m_mediaKeys);
1005 visitor->trace(m_keyStatusesMap); 1034 visitor->trace(m_keyStatusesMap);
1006 visitor->trace(m_closedPromise); 1035 visitor->trace(m_closedPromise);
1007 EventTargetWithInlineData::trace(visitor); 1036 EventTargetWithInlineData::trace(visitor);
1008 ActiveDOMObject::trace(visitor); 1037 ActiveDOMObject::trace(visitor);
1009 } 1038 }
1010 1039
1011 } // namespace blink 1040 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698