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

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

Issue 641433002: Implement MediaKeySession.load() (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 6 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 29 matching lines...) Expand all
40 #include "platform/ContentDecryptionModuleResult.h" 40 #include "platform/ContentDecryptionModuleResult.h"
41 #include "platform/ContentType.h" 41 #include "platform/ContentType.h"
42 #include "platform/Logging.h" 42 #include "platform/Logging.h"
43 #include "platform/MIMETypeRegistry.h" 43 #include "platform/MIMETypeRegistry.h"
44 #include "platform/Timer.h" 44 #include "platform/Timer.h"
45 #include "public/platform/WebContentDecryptionModule.h" 45 #include "public/platform/WebContentDecryptionModule.h"
46 #include "public/platform/WebContentDecryptionModuleException.h" 46 #include "public/platform/WebContentDecryptionModuleException.h"
47 #include "public/platform/WebContentDecryptionModuleSession.h" 47 #include "public/platform/WebContentDecryptionModuleSession.h"
48 #include "public/platform/WebString.h" 48 #include "public/platform/WebString.h"
49 #include "public/platform/WebURL.h" 49 #include "public/platform/WebURL.h"
50 #include "wtf/ASCIICType.h"
50 #include "wtf/ArrayBuffer.h" 51 #include "wtf/ArrayBuffer.h"
51 #include "wtf/ArrayBufferView.h" 52 #include "wtf/ArrayBufferView.h"
52 53
54 namespace {
55
56 // TODO Remove once close/remove CL landed.
sandersd (OOO until July 31) 2014/10/08 18:18:22 More specifically? (What is that CL doing that rel
jrummell 2014/10/08 21:13:20 Removed TODO. Will get merge conflicts, this was j
57 const char* kPersistent = "persistent";
58
59 // Minimum and maximum length for session ids.
60 enum {
61 MinSessionIdLength = 1,
62 MaxSessionIdLength = 512
63 };
64
65 } // namespace
66
53 namespace blink { 67 namespace blink {
54 68
55 static bool isKeySystemSupportedWithInitDataType(const String& keySystem, const String& initDataType) 69 static bool isKeySystemSupportedWithInitDataType(const String& keySystem, const String& initDataType)
56 { 70 {
57 ASSERT(!keySystem.isEmpty()); 71 ASSERT(!keySystem.isEmpty());
58 72
59 // FIXME: initDataType != contentType. Implement this properly. 73 // FIXME: initDataType != contentType. Implement this properly.
60 // http://crbug.com/385874. 74 // http://crbug.com/385874.
61 String contentType = initDataType; 75 String contentType = initDataType;
62 if (initDataType == "webm") { 76 if (initDataType == "webm") {
63 contentType = "video/webm"; 77 contentType = "video/webm";
64 } else if (initDataType == "cenc") { 78 } else if (initDataType == "cenc") {
65 contentType = "video/mp4"; 79 contentType = "video/mp4";
66 } 80 }
67 81
68 ContentType type(contentType); 82 ContentType type(contentType);
69 return MIMETypeRegistry::isSupportedEncryptedMediaMIMEType(keySystem, type.t ype(), type.parameter("codecs")); 83 return MIMETypeRegistry::isSupportedEncryptedMediaMIMEType(keySystem, type.t ype(), type.parameter("codecs"));
70 } 84 }
71 85
86 // Checks that |sessionId| looks correct. Returns true if all tests pass,
87 // false otherwise.
88 static bool ValidSessionId(const String& sessionId)
sandersd (OOO until July 31) 2014/10/08 18:18:22 isValidSessionId
jrummell 2014/10/08 21:13:20 Done.
89 {
90 if ((sessionId.length() < MinSessionIdLength) || (sessionId.length() > MaxSe ssionIdLength))
91 return false;
92
93 if (!sessionId.containsOnlyASCII())
94 return false;
95
96 // Check that the sessionId only contains alphanumeric characters.
97 for (unsigned i = 0; i < sessionId.length(); ++i) {
98 if (!isASCIIAlphanumeric(sessionId[i]))
99 return false;
100 }
101
102 return true;
103 }
104
72 // A class holding a pending action. 105 // A class holding a pending action.
73 class MediaKeySession::PendingAction : public GarbageCollectedFinalized<MediaKey Session::PendingAction> { 106 class MediaKeySession::PendingAction : public GarbageCollectedFinalized<MediaKey Session::PendingAction> {
74 public: 107 public:
75 enum Type { 108 enum Type {
76 GenerateRequest, 109 GenerateRequest,
110 Load,
77 Update, 111 Update,
78 Release 112 Release
79 }; 113 };
80 114
81 Type type() const { return m_type; } 115 Type type() const { return m_type; }
82 116
83 const Persistent<ContentDecryptionModuleResult> result() const 117 const Persistent<ContentDecryptionModuleResult> result() const
84 { 118 {
85 return m_result; 119 return m_result;
86 } 120 }
87 121
88 const RefPtr<ArrayBuffer> data() const 122 const RefPtr<ArrayBuffer> data() const
89 { 123 {
90 ASSERT(m_type == GenerateRequest || m_type == Update); 124 ASSERT(m_type == GenerateRequest || m_type == Update);
91 return m_data; 125 return m_data;
92 } 126 }
93 127
94 const String& initDataType() const 128 const String& initDataType() const
95 { 129 {
96 ASSERT(m_type == GenerateRequest); 130 ASSERT(m_type == GenerateRequest);
97 return m_initDataType; 131 return m_initDataType;
98 } 132 }
99 133
134 const String& sessionId() const
135 {
136 ASSERT(m_type == Load);
137 return m_initDataType;
138 }
139
100 static PendingAction* CreatePendingGenerateRequest(ContentDecryptionModuleRe sult* result, const String& initDataType, PassRefPtr<ArrayBuffer> initData) 140 static PendingAction* CreatePendingGenerateRequest(ContentDecryptionModuleRe sult* result, const String& initDataType, PassRefPtr<ArrayBuffer> initData)
101 { 141 {
102 ASSERT(result); 142 ASSERT(result);
103 ASSERT(initData); 143 ASSERT(initData);
104 return new PendingAction(GenerateRequest, result, initDataType, initData ); 144 return new PendingAction(GenerateRequest, result, initDataType, initData );
105 } 145 }
106 146
147 static PendingAction* CreatePendingLoadRequest(ContentDecryptionModuleResult * result, const String& sessionId)
148 {
149 ASSERT(result);
150 return new PendingAction(Load, result, sessionId, PassRefPtr<ArrayBuffer >());
151 }
152
107 static PendingAction* CreatePendingUpdate(ContentDecryptionModuleResult* res ult, PassRefPtr<ArrayBuffer> data) 153 static PendingAction* CreatePendingUpdate(ContentDecryptionModuleResult* res ult, PassRefPtr<ArrayBuffer> data)
108 { 154 {
109 ASSERT(result); 155 ASSERT(result);
110 ASSERT(data); 156 ASSERT(data);
111 return new PendingAction(Update, result, String(), data); 157 return new PendingAction(Update, result, String(), data);
112 } 158 }
113 159
114 static PendingAction* CreatePendingRelease(ContentDecryptionModuleResult* re sult) 160 static PendingAction* CreatePendingRelease(ContentDecryptionModuleResult* re sult)
115 { 161 {
116 ASSERT(result); 162 ASSERT(result);
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 void completeWithDOMException(ExceptionCode code, const String& errorMessage ) 244 void completeWithDOMException(ExceptionCode code, const String& errorMessage )
199 { 245 {
200 m_resolver->reject(DOMException::create(code, errorMessage)); 246 m_resolver->reject(DOMException::create(code, errorMessage));
201 m_resolver.clear(); 247 m_resolver.clear();
202 } 248 }
203 249
204 RefPtr<ScriptPromiseResolver> m_resolver; 250 RefPtr<ScriptPromiseResolver> m_resolver;
205 Member<MediaKeySession> m_session; 251 Member<MediaKeySession> m_session;
206 }; 252 };
207 253
254 // This class wraps the promise resolver used when loading a session
255 // and is passed to Chromium to fullfill the promise. This implementation of
256 // completeWithSession() will resolve the promise with true/false, while
257 // completeWithError() will reject the promise with an exception. complete()
258 // is not expected to be called, and will reject the promise.
259 class LoadSessionResult : public ContentDecryptionModuleResult {
260 public:
261 LoadSessionResult(ScriptState* scriptState, MediaKeySession* session)
262 : m_resolver(ScriptPromiseResolver::create(scriptState))
263 , m_session(session)
264 {
265 WTF_LOG(Media, "LoadSessionResult(%p)", this);
266 }
267
268 virtual ~LoadSessionResult()
269 {
270 WTF_LOG(Media, "~LoadSessionResult(%p)", this);
271 }
272
273 // ContentDecryptionModuleResult implementation.
274 virtual void complete() OVERRIDE
275 {
276 ASSERT_NOT_REACHED();
277 completeWithDOMException(InvalidStateError, "Unexpected completion.");
278 }
279
280 virtual void completeWithSession(WebContentDecryptionModuleResult::SessionSt atus status) OVERRIDE
281 {
282 bool result;
283 switch (status) {
284 case WebContentDecryptionModuleResult::NewSession:
285 result = true;
286 break;
287
288 case WebContentDecryptionModuleResult::SessionNotFound:
289 result = false;
290 break;
291
292 case WebContentDecryptionModuleResult::SessionAlreadyExists:
293 ASSERT_NOT_REACHED();
294 completeWithDOMException(InvalidStateError, "Unexpected completion." );
295 return;
296 }
297
298 m_session->finishLoadSession();
299 m_resolver->resolve(result);
300 m_resolver.clear();
301 }
302
303 virtual void completeWithError(WebContentDecryptionModuleException exception Code, unsigned long systemCode, const WebString& errorMessage) OVERRIDE
304 {
305 completeWithDOMException(WebCdmExceptionToExceptionCode(exceptionCode), errorMessage);
306 }
307
308 // It is only valid to call this before completion.
309 ScriptPromise promise() { return m_resolver->promise(); }
310
311 void trace(Visitor* visitor)
312 {
313 visitor->trace(m_session);
314 ContentDecryptionModuleResult::trace(visitor);
315 }
316
317 private:
318 // Reject the promise with a DOMException.
319 void completeWithDOMException(ExceptionCode code, const String& errorMessage )
320 {
321 m_resolver->reject(DOMException::create(code, errorMessage));
322 m_resolver.clear();
323 }
324
325 RefPtr<ScriptPromiseResolver> m_resolver;
326 Member<MediaKeySession> m_session;
327 };
328
208 MediaKeySession* MediaKeySession::create(ScriptState* scriptState, MediaKeys* me diaKeys, const String& sessionType) 329 MediaKeySession* MediaKeySession::create(ScriptState* scriptState, MediaKeys* me diaKeys, const String& sessionType)
209 { 330 {
210 RefPtrWillBeRawPtr<MediaKeySession> session = adoptRefCountedGarbageCollecte dWillBeNoop(new MediaKeySession(scriptState, mediaKeys, sessionType)); 331 RefPtrWillBeRawPtr<MediaKeySession> session = adoptRefCountedGarbageCollecte dWillBeNoop(new MediaKeySession(scriptState, mediaKeys, sessionType));
211 session->suspendIfNeeded(); 332 session->suspendIfNeeded();
212 return session.get(); 333 return session.get();
213 } 334 }
214 335
215 MediaKeySession::MediaKeySession(ScriptState* scriptState, MediaKeys* mediaKeys, const String& sessionType) 336 MediaKeySession::MediaKeySession(ScriptState* scriptState, MediaKeys* mediaKeys, const String& sessionType)
216 : ActiveDOMObject(scriptState->executionContext()) 337 : ActiveDOMObject(scriptState->executionContext())
217 , m_keySystem(mediaKeys->keySystem()) 338 , m_keySystem(mediaKeys->keySystem())
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 // 10. Run the following steps asynchronously (documented in 470 // 10. Run the following steps asynchronously (documented in
350 // actionTimerFired()) 471 // actionTimerFired())
351 m_pendingActions.append(PendingAction::CreatePendingGenerateRequest(result, initDataType, initData)); 472 m_pendingActions.append(PendingAction::CreatePendingGenerateRequest(result, initDataType, initData));
352 ASSERT(!m_actionTimer.isActive()); 473 ASSERT(!m_actionTimer.isActive());
353 m_actionTimer.startOneShot(0, FROM_HERE); 474 m_actionTimer.startOneShot(0, FROM_HERE);
354 475
355 // 11. Return promise. 476 // 11. Return promise.
356 return promise; 477 return promise;
357 } 478 }
358 479
480 ScriptPromise MediaKeySession::load(ScriptState* scriptState, const String& sess ionId)
481 {
482 WTF_LOG(Media, "MediaKeySession(%p)::load %s", this, sessionId.ascii().data( ));
483
484 // From https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/e ncrypted-media.html#dom-load:
485 // The load(sessionId) method loads the data stored for the sessionId into
486 // the session represented by the object. It must run the following steps:
487
488 // 1. If this object's uninitialized value is false, return a promise
489 // rejected with a new DOMException whose name is "InvalidStateError".
490 if (!m_isUninitialized) {
491 return ScriptPromise::rejectWithDOMException(
492 scriptState, DOMException::create(InvalidStateError, "The session is already initialized."));
493 }
494
495 // 2. Let this object's uninitialized be false.
496 m_isUninitialized = false;
497
498 // 3. If sessionId is an empty string, return a promise rejected with a
499 // new DOMException whose name is "InvalidAccessError".
500 if (sessionId.isEmpty()) {
501 return ScriptPromise::rejectWithDOMException(
502 scriptState, DOMException::create(InvalidAccessError, "The sessionId parameter is empty."));
503 }
504
505 // 4. If this object's session type is not "persistent", return a promise
506 // rejected with a new DOMException whose name is "InvalidAccessError".
507 if (m_sessionType != kPersistent) {
508 return ScriptPromise::rejectWithDOMException(
509 scriptState, DOMException::create(InvalidAccessError, "The session t ype is not \"persistent\"."));
510 }
511
512 // 5. Let media keys be the MediaKeys object that created this object.
513 // (Done in constructor.)
514 ASSERT(m_mediaKeys);
515
516 // 6. If the content decryption module corresponding to media keys's
517 // keySystem attribute does not support loading previous sessions,
518 // return a promise rejected with a new DOMException whose name is
519 // "NotSupportedError".
520 // (Done by CDM.)
521
522 // 7. Let promise be a new promise.
523 LoadSessionResult* result = new LoadSessionResult(scriptState, this);
524 ScriptPromise promise = result->promise();
525
526 // 8. Run the following steps asynchronously (documented in
527 // actionTimerFired())
528 m_pendingActions.append(PendingAction::CreatePendingLoadRequest(result, sess ionId));
529 ASSERT(!m_actionTimer.isActive());
530 m_actionTimer.startOneShot(0, FROM_HERE);
531
532 // 9. Return promise.
533 return promise;
534 }
535
359 ScriptPromise MediaKeySession::update(ScriptState* scriptState, ArrayBuffer* res ponse) 536 ScriptPromise MediaKeySession::update(ScriptState* scriptState, ArrayBuffer* res ponse)
360 { 537 {
361 RefPtr<ArrayBuffer> responseCopy = ArrayBuffer::create(response->data(), res ponse->byteLength()); 538 RefPtr<ArrayBuffer> responseCopy = ArrayBuffer::create(response->data(), res ponse->byteLength());
362 return updateInternal(scriptState, responseCopy.release()); 539 return updateInternal(scriptState, responseCopy.release());
363 } 540 }
364 541
365 ScriptPromise MediaKeySession::update(ScriptState* scriptState, ArrayBufferView* response) 542 ScriptPromise MediaKeySession::update(ScriptState* scriptState, ArrayBufferView* response)
366 { 543 {
367 RefPtr<ArrayBuffer> responseCopy = ArrayBuffer::create(response->baseAddress (), response->byteLength()); 544 RefPtr<ArrayBuffer> responseCopy = ArrayBuffer::create(response->baseAddress (), response->byteLength());
368 return updateInternal(scriptState, responseCopy.release()); 545 return updateInternal(scriptState, responseCopy.release());
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
464 // "NotSupportedError". 641 // "NotSupportedError".
465 // 10.3.3 Let request be a request (e.g. a license request) 642 // 10.3.3 Let request be a request (e.g. a license request)
466 // generated based on the init data, which is interpreted 643 // generated based on the init data, which is interpreted
467 // per initDataType, and session type. 644 // per initDataType, and session type.
468 m_session->initializeNewSession(action->initDataType(), static_cast< unsigned char*>(action->data()->data()), action->data()->byteLength(), m_session Type, action->result()->result()); 645 m_session->initializeNewSession(action->initDataType(), static_cast< unsigned char*>(action->data()->data()), action->data()->byteLength(), m_session Type, action->result()->result());
469 646
470 // Remainder of steps executed in finishGenerateRequest(), called 647 // Remainder of steps executed in finishGenerateRequest(), called
471 // when |result| is resolved. 648 // when |result| is resolved.
472 break; 649 break;
473 650
651 case PendingAction::Load:
652 // NOTE: Continue step 8 of MediaKeySession::load().
653
654 // 8.1 Let sanitized session ID be a validated and/or sanitized
655 // version of sessionId. The user agent should thoroughly
656 // validate the sessionId value before passing it to the CDM.
657 // At a minimum, this should include checking that the length
658 // and value (e.g. alphanumeric) are reasonable.
659 // 8.2 If the previous step failed, reject promise with a new
660 // DOMException whose name is "InvalidAccessError".
661 if (!ValidSessionId(action->sessionId())) {
662 action->result()->completeWithError(WebContentDecryptionModuleEx ceptionInvalidAccessError, 0, "Invalid sessionId");
663 return;
664 }
665
666 // 8.3 Let expiration time be NaN.
667 // (Already done in the constructor.)
668 // TODO once expiration change merged in.
sandersd (OOO until July 31) 2014/10/08 18:18:22 I don't recall an expiration CL, perhaps this shou
jrummell 2014/10/08 21:13:20 The other CL is https://codereview.chromium.org/62
669 // ASSERT(std::isnan(m_expiration));
670
671 // 8.4 Let message be null.
672 // 8.5 Let message type be null.
673 // (Will be provided by the CDM if needed.)
674
675 // 8.6 Let origin be the origin of this object's Document.
676 // (Obtained previously when CDM created.)
677
678 // 8.7 Let cdm be the CDM loaded during the initialization of media
679 // keys.
680 // 8.8 Use the cdm to execute the following steps:
681 // 8.8.1 If there is no data stored for the sanitized session ID in
682 // the origin, resolve promise with false.
683 // 8.8.2 Let session data be the data stored for the sanitized
684 // session ID in the origin. This must not include data from
685 // other origin(s) or that is not associated with an origin.
686 // 8.8.3 If there is an unclosed "persistent" session in any
687 // Document representing the session data, reject promise
688 // with a new DOMException whose name is "QuotaExceededError".
689 // 8.8.4 In other words, do not create a session if a non-closed
690 // persistent session already exists for this sanitized
691 // session ID in any browsing context.
692 // 8.8.5 Load the session data.
693 // 8.8.6 If the session data indicates an expiration time for the
694 // session, let expiration time be the expiration time
695 // in milliseconds since 01 January 1970 UTC.
696 // 8.8.6 If the CDM needs to send a message:
697 // 8.8.6.1 Let message be a message generated by the CDM based on
698 // the session data.
699 // 8.8.6.2 Let message type be the appropriate MediaKeyMessageType
700 // for the message.
701 // 8.9 If any of the preceding steps failed, reject promise with a
702 // new DOMException whose name is the appropriate error name.
703 m_session->loadSession(action->sessionId(), action->result()->result ());
704
705 // Remainder of steps executed in finishLoadSession(), called
706 // when |result| is resolved.
707 break;
708
474 case PendingAction::Update: 709 case PendingAction::Update:
475 WTF_LOG(Media, "MediaKeySession(%p)::actionTimerFired: Update", this ); 710 WTF_LOG(Media, "MediaKeySession(%p)::actionTimerFired: Update", this );
476 // NOTE: Continued from step 4 of MediaKeySession::update(). 711 // NOTE: Continued from step 4 of MediaKeySession::update().
477 // Continue the update call by passing message to the cdm. Once 712 // Continue the update call by passing message to the cdm. Once
478 // completed, it will resolve/reject the promise. 713 // completed, it will resolve/reject the promise.
479 m_session->update(static_cast<unsigned char*>(action->data()->data() ), action->data()->byteLength(), action->result()->result()); 714 m_session->update(static_cast<unsigned char*>(action->data()->data() ), action->data()->byteLength(), action->result()->result());
480 break; 715 break;
481 716
482 case PendingAction::Release: 717 case PendingAction::Release:
483 WTF_LOG(Media, "MediaKeySession(%p)::actionTimerFired: Release", thi s); 718 WTF_LOG(Media, "MediaKeySession(%p)::actionTimerFired: Release", thi s);
(...skipping 26 matching lines...) Expand all
510 // https://www.w3.org/Bugs/Public/show_bug.cgi?id=26758 745 // https://www.w3.org/Bugs/Public/show_bug.cgi?id=26758
511 746
512 // 10.7 Run the Queue a "message" Event algorithm on the session, 747 // 10.7 Run the Queue a "message" Event algorithm on the session,
513 // providing request and null. 748 // providing request and null.
514 // (Done by the CDM). 749 // (Done by the CDM).
515 750
516 // 10.8 Let this object's callable be true. 751 // 10.8 Let this object's callable be true.
517 m_isCallable = true; 752 m_isCallable = true;
518 } 753 }
519 754
755 void MediaKeySession::finishLoadSession()
756 {
757 // 8.10 Set the sessionId attribute to sanitized session ID.
758 ASSERT(!sessionId().isEmpty());
759
760 // 8.11 Let this object's callable be true.
761 m_isCallable = true;
762
763 // 8.12 If the loaded session contains usable keys, run the Usable
764 // Keys Changed algorithm on the session. The algorithm may
765 // also be run later should additional processing be necessary
766 // to determine with certainty whether one or more keys is
767 // usable.
768 // (Done by the CDM.)
769
770 // 8.13 Run the Update Expiration algorithm on the session,
771 // providing expiration time.
772 // (Done by the CDM.)
773
774 // 8.14 If message is not null, run the Queue a "message" Event
775 // algorithm on the session, providing message type and
776 // message.
777 // (Done by the CDM.)
778 }
779
520 // Queue a task to fire a simple event named keymessage at the new object. 780 // Queue a task to fire a simple event named keymessage at the new object.
521 void MediaKeySession::message(const unsigned char* message, size_t messageLength , const WebURL& destinationURL) 781 void MediaKeySession::message(const unsigned char* message, size_t messageLength , const WebURL& destinationURL)
522 { 782 {
523 WTF_LOG(Media, "MediaKeySession(%p)::message", this); 783 WTF_LOG(Media, "MediaKeySession(%p)::message", this);
524 784
525 // Verify that 'message' not fired before session initialization is complete . 785 // Verify that 'message' not fired before session initialization is complete .
526 ASSERT(m_isCallable); 786 ASSERT(m_isCallable);
527 787
528 MediaKeyMessageEventInit init; 788 MediaKeyMessageEventInit init;
529 init.bubbles = false; 789 init.bubbles = false;
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
647 { 907 {
648 visitor->trace(m_error); 908 visitor->trace(m_error);
649 visitor->trace(m_asyncEventQueue); 909 visitor->trace(m_asyncEventQueue);
650 visitor->trace(m_pendingActions); 910 visitor->trace(m_pendingActions);
651 visitor->trace(m_mediaKeys); 911 visitor->trace(m_mediaKeys);
652 visitor->trace(m_closedPromise); 912 visitor->trace(m_closedPromise);
653 EventTargetWithInlineData::trace(visitor); 913 EventTargetWithInlineData::trace(visitor);
654 } 914 }
655 915
656 } // namespace blink 916 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698