1926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/*
2926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * Copyright (C) 2013 Apple Inc. All rights reserved.
3926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) *
4926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * Redistribution and use in source and binary forms, with or without
5926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * modification, are permitted provided that the following conditions
6926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * are met:
7926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * 1. Redistributions of source code must retain the above copyright
8926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) *    notice, this list of conditions and the following disclaimer.
9926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright
10926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) *    notice, this list of conditions and the following disclaimer in the
11926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) *    documentation and/or other materials provided with the distribution.
12926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) *
13926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * THE POSSIBILITY OF SUCH DAMAGE.
24926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
25926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
26926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)#include "config.h"
2753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/encryptedmedia/MediaKeySession.h"
28926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
29c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "bindings/core/v8/DOMWrapperWorld.h"
30197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "bindings/core/v8/ScriptPromise.h"
31197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "bindings/core/v8/ScriptPromiseResolver.h"
32197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "bindings/core/v8/ScriptState.h"
337757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "core/dom/ExceptionCode.h"
34197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "core/events/Event.h"
3506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)#include "core/events/GenericEventQueue.h"
3653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/html/MediaKeyError.h"
3753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/encryptedmedia/MediaKeyMessageEvent.h"
3853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/encryptedmedia/MediaKeys.h"
39197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "modules/encryptedmedia/SimpleContentDecryptionModuleResult.h"
40197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "platform/ContentDecryptionModuleResult.h"
417242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "platform/ContentType.h"
4209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "platform/Logging.h"
437242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "platform/MIMETypeRegistry.h"
44197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "platform/Timer.h"
45d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "public/platform/WebContentDecryptionModule.h"
46197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "public/platform/WebContentDecryptionModuleException.h"
47197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "public/platform/WebContentDecryptionModuleSession.h"
48d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "public/platform/WebString.h"
49d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "public/platform/WebURL.h"
50c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "wtf/ArrayBuffer.h"
51c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "wtf/ArrayBufferView.h"
52926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
53c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
54926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
557242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccistatic bool isKeySystemSupportedWithInitDataType(const String& keySystem, const String& initDataType)
567242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{
577242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    ASSERT(!keySystem.isEmpty());
587242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
597242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // FIXME: initDataType != contentType. Implement this properly.
607242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // http://crbug.com/385874.
617242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    String contentType = initDataType;
627242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (initDataType == "webm") {
637242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        contentType = "video/webm";
647242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    } else if (initDataType == "cenc") {
657242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        contentType = "video/mp4";
667242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
677242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
687242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    ContentType type(contentType);
697242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    return MIMETypeRegistry::isSupportedEncryptedMediaMIMEType(keySystem, type.type(), type.parameter("codecs"));
707242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}
717242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
72197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// A class holding a pending action.
73197021e6b966cfb06891637935ef33fff06433d1Ben Murdochclass MediaKeySession::PendingAction : public GarbageCollectedFinalized<MediaKeySession::PendingAction> {
74197021e6b966cfb06891637935ef33fff06433d1Ben Murdochpublic:
75197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    enum Type {
767242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        GenerateRequest,
77197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        Update,
787242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        Release
79197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    };
80197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
81197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    Type type() const { return m_type; }
82e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)
83e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    const Persistent<ContentDecryptionModuleResult> result() const
84e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    {
85e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        return m_result;
86e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    }
87e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)
88e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    const RefPtr<ArrayBuffer> data() const
89e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    {
907242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        ASSERT(m_type == GenerateRequest || m_type == Update);
91e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        return m_data;
92e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    }
93e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)
947242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    const String& initDataType() const
95e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    {
967242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        ASSERT(m_type == GenerateRequest);
977242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        return m_initDataType;
98e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    }
99197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
1007242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    static PendingAction* CreatePendingGenerateRequest(ContentDecryptionModuleResult* result, const String& initDataType, PassRefPtr<ArrayBuffer> initData)
101197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    {
102197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        ASSERT(result);
1037242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        ASSERT(initData);
1047242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        return new PendingAction(GenerateRequest, result, initDataType, initData);
105197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    }
106197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
1077242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    static PendingAction* CreatePendingUpdate(ContentDecryptionModuleResult* result, PassRefPtr<ArrayBuffer> data)
108197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    {
109197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        ASSERT(result);
1107242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        ASSERT(data);
1117242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        return new PendingAction(Update, result, String(), data);
112197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    }
113197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
1147242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    static PendingAction* CreatePendingRelease(ContentDecryptionModuleResult* result)
115e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    {
1167242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        ASSERT(result);
1177242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        return new PendingAction(Release, result, String(), PassRefPtr<ArrayBuffer>());
118e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    }
119e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)
120197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ~PendingAction()
121197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    {
122197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    }
123197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
124197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    void trace(Visitor* visitor)
125197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    {
126197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        visitor->trace(m_result);
127197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    }
128197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
129197021e6b966cfb06891637935ef33fff06433d1Ben Murdochprivate:
1307242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    PendingAction(Type type, ContentDecryptionModuleResult* result, const String& initDataType, PassRefPtr<ArrayBuffer> data)
131197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        : m_type(type)
132197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        , m_result(result)
1337242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        , m_initDataType(initDataType)
134197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        , m_data(data)
135197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    {
136197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    }
137197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
138197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    const Type m_type;
139197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    const Member<ContentDecryptionModuleResult> m_result;
1407242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    const String m_initDataType;
141c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    const RefPtr<ArrayBuffer> m_data;
142197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch};
143197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
1447242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// This class wraps the promise resolver used when initializing a new session
1457242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// and is passed to Chromium to fullfill the promise. This implementation of
1467242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// completeWithSession() will resolve the promise with void, while
1477242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// completeWithError() will reject the promise with an exception. complete()
1487242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// is not expected to be called, and will reject the promise.
1497242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciclass NewSessionResult : public ContentDecryptionModuleResult {
150197021e6b966cfb06891637935ef33fff06433d1Ben Murdochpublic:
1517242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    NewSessionResult(ScriptState* scriptState, MediaKeySession* session)
1527242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        : m_resolver(ScriptPromiseResolver::create(scriptState))
1537242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        , m_session(session)
1547242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    {
1557242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        WTF_LOG(Media, "NewSessionResult(%p)", this);
1567242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
157197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
1587242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    virtual ~NewSessionResult()
159197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    {
1607242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        WTF_LOG(Media, "~NewSessionResult(%p)", this);
161197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    }
162197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
163197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // ContentDecryptionModuleResult implementation.
164197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    virtual void complete() OVERRIDE
165197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    {
166197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        ASSERT_NOT_REACHED();
1677242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        completeWithDOMException(InvalidStateError, "Unexpected completion.");
168197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    }
169197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
170e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    virtual void completeWithSession(WebContentDecryptionModuleResult::SessionStatus status) OVERRIDE
171197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    {
1727242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        if (status != WebContentDecryptionModuleResult::NewSession) {
1737242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            ASSERT_NOT_REACHED();
1747242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            completeWithDOMException(InvalidStateError, "Unexpected completion.");
1757242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        }
1767242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
1777242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        m_session->finishGenerateRequest();
1787242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        m_resolver->resolve();
1797242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        m_resolver.clear();
180197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    }
181197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
1827242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    virtual void completeWithError(WebContentDecryptionModuleException exceptionCode, unsigned long systemCode, const WebString& errorMessage) OVERRIDE
183197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    {
1847242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        completeWithDOMException(WebCdmExceptionToExceptionCode(exceptionCode), errorMessage);
185197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    }
186197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
1877242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // It is only valid to call this before completion.
1887242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    ScriptPromise promise() { return m_resolver->promise(); }
189197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
1907242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    void trace(Visitor* visitor)
1917242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    {
1927242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        visitor->trace(m_session);
1937242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        ContentDecryptionModuleResult::trace(visitor);
194197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    }
195197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
1967242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciprivate:
1977242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // Reject the promise with a DOMException.
1987242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    void completeWithDOMException(ExceptionCode code, const String& errorMessage)
1997242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    {
2007242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        m_resolver->reject(DOMException::create(code, errorMessage));
2017242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        m_resolver.clear();
202197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    }
203d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
2047242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    RefPtr<ScriptPromiseResolver> m_resolver;
2057242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    Member<MediaKeySession> m_session;
2067242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci};
20709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
2087242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano TucciMediaKeySession* MediaKeySession::create(ScriptState* scriptState, MediaKeys* mediaKeys, const String& sessionType)
209926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
2107242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    RefPtrWillBeRawPtr<MediaKeySession> session = adoptRefCountedGarbageCollectedWillBeNoop(new MediaKeySession(scriptState, mediaKeys, sessionType));
2117242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    session->suspendIfNeeded();
2127242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    return session.get();
213926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
214926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2157242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano TucciMediaKeySession::MediaKeySession(ScriptState* scriptState, MediaKeys* mediaKeys, const String& sessionType)
2167242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    : ActiveDOMObject(scriptState->executionContext())
2177242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    , m_keySystem(mediaKeys->keySystem())
218f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    , m_asyncEventQueue(GenericEventQueue::create(this))
2197242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    , m_mediaKeys(mediaKeys)
2207242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    , m_sessionType(sessionType)
2217242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    , m_isUninitialized(true)
2227242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    , m_isCallable(false)
223d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    , m_isClosed(false)
2247242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    , m_closedPromise(new ClosedPromise(scriptState->executionContext(), this, ClosedPromise::Closed))
225d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    , m_actionTimer(this, &MediaKeySession::actionTimerFired)
226926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
227197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    WTF_LOG(Media, "MediaKeySession(%p)::MediaKeySession", this);
2287242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
2297242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // Create the matching Chromium object. It will not be usable until
2307242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // initializeNewSession() is called in response to the user calling
2317242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // generateRequest().
2327242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    WebContentDecryptionModule* cdm = mediaKeys->contentDecryptionModule();
2337242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    m_session = adoptPtr(cdm->createSession());
234197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    m_session->setClientInterface(this);
235197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
2367242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // MediaKeys::createSession(), step 2.
2377242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // 2.1 Let the sessionId attribute be the empty string.
2387242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    ASSERT(sessionId().isEmpty());
239197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
2407242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // 2.2 Let the expiration attribute be NaN.
2417242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // FIXME: Add expiration property.
2427242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
2437242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // 2.3 Let the closed attribute be a new promise.
2447242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    ASSERT(!closed(scriptState).isUndefinedOrNull());
2457242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
2467242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // 2.4 Let the session type be sessionType.
2477242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    ASSERT(sessionType == m_sessionType);
2487242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
2497242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // 2.5 Let uninitialized be true.
2507242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    ASSERT(m_isUninitialized);
251197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
2527242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // 2.6 Let callable be false.
2537242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    ASSERT(!m_isCallable);
254926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
255926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
256926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)MediaKeySession::~MediaKeySession()
257926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
258197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    WTF_LOG(Media, "MediaKeySession(%p)::~MediaKeySession", this);
25909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    m_session.clear();
2605d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)#if !ENABLE(OILPAN)
2615d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // MediaKeySession and m_asyncEventQueue always become unreachable
2625d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // together. So MediaKeySession and m_asyncEventQueue are destructed in the
2635d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // same GC. We don't need to call cancelAllEvents explicitly in Oilpan.
26409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    m_asyncEventQueue->cancelAllEvents();
2655d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)#endif
266926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
267926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
268926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void MediaKeySession::setError(MediaKeyError* error)
269926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
270926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    m_error = error;
271926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
272926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
273521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)String MediaKeySession::sessionId() const
274926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
275926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return m_session->sessionId();
276926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
277926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
278c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)ScriptPromise MediaKeySession::closed(ScriptState* scriptState)
279c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){
280c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    return m_closedPromise->promise(scriptState->world());
281c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
282c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
2837242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano TucciScriptPromise MediaKeySession::generateRequest(ScriptState* scriptState, const String& initDataType, ArrayBuffer* initData)
2847242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{
2857242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    RefPtr<ArrayBuffer> initDataCopy = ArrayBuffer::create(initData->data(), initData->byteLength());
2867242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    return generateRequestInternal(scriptState, initDataType, initDataCopy.release());
2877242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}
2887242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
2897242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano TucciScriptPromise MediaKeySession::generateRequest(ScriptState* scriptState, const String& initDataType, ArrayBufferView* initData)
2907242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{
2917242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    RefPtr<ArrayBuffer> initDataCopy = ArrayBuffer::create(initData->baseAddress(), initData->byteLength());
2927242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    return generateRequestInternal(scriptState, initDataType, initDataCopy.release());
2937242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}
2947242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
2957242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano TucciScriptPromise MediaKeySession::generateRequestInternal(ScriptState* scriptState, const String& initDataType, PassRefPtr<ArrayBuffer> initData)
2967242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{
2977242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    WTF_LOG(Media, "MediaKeySession(%p)::generateRequest %s", this, initDataType.ascii().data());
2987242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
2997242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // From https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html#dom-generaterequest:
3007242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // The generateRequest(initDataType, initData) method creates a new session
3017242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // for the specified initData. It must run the following steps:
3027242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
3037242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // 1. If this object's uninitialized value is false, return a promise
3047242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    //    rejected with a new DOMException whose name is "InvalidStateError".
3057242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (!m_isUninitialized) {
3067242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        return ScriptPromise::rejectWithDOMException(
3077242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            scriptState, DOMException::create(InvalidStateError, "The session is already initialized."));
3087242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
3097242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
3107242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // 2. Let this object's uninitialized be false.
3117242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    m_isUninitialized = false;
3127242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
3137242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // 3. If initDataType is an empty string, return a promise rejected with a
3147242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    //    new DOMException whose name is "InvalidAccessError".
3157242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (initDataType.isEmpty()) {
3167242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        return ScriptPromise::rejectWithDOMException(
3177242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            scriptState, DOMException::create(InvalidAccessError, "The initDataType parameter is empty."));
3187242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
3197242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
3207242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // 4. If initData is an empty array, return a promise rejected with a new
3217242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    //    DOMException whose name is"InvalidAccessError".
3227242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (!initData->byteLength()) {
3237242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        return ScriptPromise::rejectWithDOMException(
3247242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            scriptState, DOMException::create(InvalidAccessError, "The initData parameter is empty."));
3257242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
3267242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
3277242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // 5. Let media keys be the MediaKeys object that created this object.
3287242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    //    (Use m_mediaKey, which was set in the constructor.)
3297242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
3307242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // 6. If the content decryption module corresponding to media keys's
3317242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    //    keySystem attribute does not support initDataType as an initialization
3327242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    //    data type, return a promise rejected with a new DOMException whose
3337242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    //    name is "NotSupportedError". String comparison is case-sensitive.
3347242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (!isKeySystemSupportedWithInitDataType(m_keySystem, initDataType)) {
3357242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        return ScriptPromise::rejectWithDOMException(
3367242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            scriptState, DOMException::create(NotSupportedError, "The initialization data type '" + initDataType + "' is not supported by the key system."));
3377242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
3387242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
3397242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // 7. Let init data be a copy of the contents of the initData parameter.
3407242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    //    (Done before calling this method.)
3417242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
3427242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // 8. Let session type be this object's session type.
3437242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    //    (Done in constructor.)
3447242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
3457242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // 9. Let promise be a new promise.
3467242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    NewSessionResult* result = new NewSessionResult(scriptState, this);
3477242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    ScriptPromise promise = result->promise();
3487242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
3497242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // 10. Run the following steps asynchronously (documented in
3507242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    //     actionTimerFired())
3517242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    m_pendingActions.append(PendingAction::CreatePendingGenerateRequest(result, initDataType, initData));
3527242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    ASSERT(!m_actionTimer.isActive());
3537242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    m_actionTimer.startOneShot(0, FROM_HERE);
3547242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
3557242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // 11. Return promise.
3567242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    return promise;
3577242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}
3587242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
359c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)ScriptPromise MediaKeySession::update(ScriptState* scriptState, ArrayBuffer* response)
360c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){
361c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    RefPtr<ArrayBuffer> responseCopy = ArrayBuffer::create(response->data(), response->byteLength());
362c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    return updateInternal(scriptState, responseCopy.release());
363c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
364c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
365c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)ScriptPromise MediaKeySession::update(ScriptState* scriptState, ArrayBufferView* response)
366c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){
367c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    RefPtr<ArrayBuffer> responseCopy = ArrayBuffer::create(response->baseAddress(), response->byteLength());
368c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    return updateInternal(scriptState, responseCopy.release());
369c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
370c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
371c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)ScriptPromise MediaKeySession::updateInternal(ScriptState* scriptState, PassRefPtr<ArrayBuffer> response)
372926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
373197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    WTF_LOG(Media, "MediaKeySession(%p)::update", this);
374d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    ASSERT(!m_isClosed);
37509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
37609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // From <https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html#dom-update>:
377197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // The update(response) method provides messages, including licenses, to the
378197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // CDM. It must run the following steps:
379197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    //
380197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // 1. If response is an empty array, return a promise rejected with a new
381197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    //    DOMException whose name is "InvalidAccessError" and that has the
382197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    //    message "The response parameter is empty."
383c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (!response->byteLength()) {
384197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return ScriptPromise::rejectWithDOMException(
385197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            scriptState, DOMException::create(InvalidAccessError, "The response parameter is empty."));
38609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
387926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
388197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // 2. Let message be a copy of the contents of the response parameter.
389c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    //    (Copied in the caller.)
390926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
391197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // 3. Let promise be a new promise.
392197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    SimpleContentDecryptionModuleResult* result = new SimpleContentDecryptionModuleResult(scriptState);
393197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ScriptPromise promise = result->promise();
394926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
395197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // 4. Run the following steps asynchronously (documented in
396197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    //    actionTimerFired())
397c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    m_pendingActions.append(PendingAction::CreatePendingUpdate(result, response));
398d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (!m_actionTimer.isActive())
399d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        m_actionTimer.startOneShot(0, FROM_HERE);
400197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
401197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // 5. Return promise.
402197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    return promise;
40309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
404926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
405197021e6b966cfb06891637935ef33fff06433d1Ben MurdochScriptPromise MediaKeySession::release(ScriptState* scriptState)
40609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
407197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    WTF_LOG(Media, "MediaKeySession(%p)::release", this);
408197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    SimpleContentDecryptionModuleResult* result = new SimpleContentDecryptionModuleResult(scriptState);
409197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ScriptPromise promise = result->promise();
410197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
411197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // From <https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html#dom-close>:
412197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // The close() method allows an application to indicate that it no longer
413197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // needs the session and the CDM should release any resources associated
414197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // with this object and close it. The returned promise is resolved when the
415197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // request has been processed, and the closed attribute promise is resolved
416197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // when the session is closed. It must run the following steps:
417197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    //
418197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // 1. If the Session Close algorithm has been run on this object, return a
419197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    //    promise fulfilled with undefined.
420197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (m_isClosed) {
421197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        result->complete();
422197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return promise;
423197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    }
42409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
425197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // 2. Let promise be a new promise.
426197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // (Created earlier so it was available in step 1.)
42709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
428197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // 3. Run the following steps asynchronously (documented in
429197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    //    actionTimerFired()).
430197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    m_pendingActions.append(PendingAction::CreatePendingRelease(result));
431d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (!m_actionTimer.isActive())
432d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        m_actionTimer.startOneShot(0, FROM_HERE);
433197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
434197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // 4. Return promise.
435197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    return promise;
436d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
437d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
438d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)void MediaKeySession::actionTimerFired(Timer<MediaKeySession>*)
439d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
440d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    ASSERT(m_pendingActions.size());
441d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
442197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // Resolving promises now run synchronously and may result in additional
443197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // actions getting added to the queue. As a result, swap the queue to
444197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // a local copy to avoid problems if this happens.
445197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    HeapDeque<Member<PendingAction> > pendingActions;
446197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    pendingActions.swap(m_pendingActions);
447d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
448197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    while (!pendingActions.isEmpty()) {
449197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        PendingAction* action = pendingActions.takeFirst();
450197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
451197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        switch (action->type()) {
4527242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        case PendingAction::GenerateRequest:
4537242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            WTF_LOG(Media, "MediaKeySession(%p)::actionTimerFired: GenerateRequest", this);
4547242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
4557242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            // 10.1 Let request be null.
4567242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            // 10.2 Let cdm be the CDM loaded during the initialization of
4577242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            //      media keys.
4587242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            // 10.3 Use the cdm to execute the following steps:
4597242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            // 10.3.1 If the init data is not valid for initDataType, reject
4607242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            //        promise with a new DOMException whose name is
4617242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            //        "InvalidAccessError".
4627242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            // 10.3.2 If the init data is not supported by the cdm, reject
4637242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            //        promise with a new DOMException whose name is
4647242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            //        "NotSupportedError".
4657242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            // 10.3.3 Let request be a request (e.g. a license request)
4667242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            //        generated based on the init data, which is interpreted
4677242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            //        per initDataType, and session type.
4687242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            m_session->initializeNewSession(action->initDataType(), static_cast<unsigned char*>(action->data()->data()), action->data()->byteLength(), m_sessionType, action->result()->result());
4697242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
4707242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            // Remainder of steps executed in finishGenerateRequest(), called
4717242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            // when |result| is resolved.
4727242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            break;
4737242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
474d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        case PendingAction::Update:
475197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            WTF_LOG(Media, "MediaKeySession(%p)::actionTimerFired: Update", this);
476197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            // NOTE: Continued from step 4 of MediaKeySession::update().
477197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            // Continue the update call by passing message to the cdm. Once
478197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            // completed, it will resolve/reject the promise.
479c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            m_session->update(static_cast<unsigned char*>(action->data()->data()), action->data()->byteLength(), action->result()->result());
480d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            break;
4817242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
482d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        case PendingAction::Release:
483197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            WTF_LOG(Media, "MediaKeySession(%p)::actionTimerFired: Release", this);
484197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            // NOTE: Continued from step 3 of MediaKeySession::release().
485197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            // 3.1 Let cdm be the cdm loaded in create().
486197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            // 3.2 Use the cdm to execute the following steps:
487197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            // 3.2.1 Process the close request. Do not remove stored session data.
488197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            // 3.2.2 If the previous step caused the session to be closed, run the
489197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            //       Session Close algorithm on this object.
490197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            // 3.3 Resolve promise with undefined.
491197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            m_session->release(action->result()->result());
492d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            break;
493d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        }
494926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
495926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
496926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4977242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccivoid MediaKeySession::finishGenerateRequest()
4987242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{
4997242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // 10.4 Set the sessionId attribute to a unique Session ID string.
5007242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    //      It may be obtained from cdm.
5017242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    ASSERT(!sessionId().isEmpty());
5027242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
5037242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // 10.5 If any of the preceding steps failed, reject promise with a new
5047242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    //      DOMException whose name is the appropriate error name.
5057242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    //      (Done by call to completeWithError()).
5067242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
5077242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // 10.6 Add an entry for the value of the sessionId attribute to
5087242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    //      media keys's list of active session IDs.
5097242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // FIXME: Is this required?
5107242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // https://www.w3.org/Bugs/Public/show_bug.cgi?id=26758
5117242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
5127242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // 10.7 Run the Queue a "message" Event algorithm on the session,
5137242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    //      providing request and null.
5147242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    //      (Done by the CDM).
5157242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
5167242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // 10.8 Let this object's callable be true.
5177242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    m_isCallable = true;
5187242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}
5197242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
5207242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// Queue a task to fire a simple event named keymessage at the new object.
521e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)void MediaKeySession::message(const unsigned char* message, size_t messageLength, const WebURL& destinationURL)
522926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
523197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    WTF_LOG(Media, "MediaKeySession(%p)::message", this);
52409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
5257242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // Verify that 'message' not fired before session initialization is complete.
5267242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    ASSERT(m_isCallable);
5277242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
52809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    MediaKeyMessageEventInit init;
52909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    init.bubbles = false;
53009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    init.cancelable = false;
531c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    init.message = ArrayBuffer::create(static_cast<const void*>(message), messageLength);
532d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    init.destinationURL = destinationURL.string();
533926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
534a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    RefPtrWillBeRawPtr<MediaKeyMessageEvent> event = MediaKeyMessageEvent::create(EventTypeNames::message, init);
53509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    event->setTarget(this);
53609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    m_asyncEventQueue->enqueueEvent(event.release());
537926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
538926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
53909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void MediaKeySession::ready()
540926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
541197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    WTF_LOG(Media, "MediaKeySession(%p)::ready", this);
542926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
543a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    RefPtrWillBeRawPtr<Event> event = Event::create(EventTypeNames::ready);
54409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    event->setTarget(this);
54509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    m_asyncEventQueue->enqueueEvent(event.release());
546521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
547521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
54809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void MediaKeySession::close()
549521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
550197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    WTF_LOG(Media, "MediaKeySession(%p)::close", this);
551d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
552d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // Once closed, the session can no longer be the target of events from
553d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // the CDM so this object can be garbage collected.
554d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    m_isClosed = true;
555197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
556c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    // Resolve the closed promise.
557c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    m_closedPromise->resolve(V8UndefinedType());
558521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
559521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
560521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)// Queue a task to fire a simple event named keyadded at the MediaKeySession object.
56109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void MediaKeySession::error(MediaKeyErrorCode errorCode, unsigned long systemCode)
562521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
563197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    WTF_LOG(Media, "MediaKeySession(%p)::error: errorCode=%d, systemCode=%lu", this, errorCode, systemCode);
56409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
565521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    MediaKeyError::Code mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_UNKNOWN;
566521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    switch (errorCode) {
567d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    case MediaKeyErrorCodeUnknown:
568521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_UNKNOWN;
569521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        break;
570d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    case MediaKeyErrorCodeClient:
571521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_CLIENT;
572521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        break;
573926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
574521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
575521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // 1. Create a new MediaKeyError object with the following attributes:
576521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    //    code = the appropriate MediaKeyError code
577521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    //    systemCode = a Key System-specific value, if provided, and 0 otherwise
578521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // 2. Set the MediaKeySession object's error attribute to the error object created in the previous step.
579521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    m_error = MediaKeyError::create(mediaKeyErrorCode, systemCode);
580521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
581521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // 3. queue a task to fire a simple event named keyerror at the MediaKeySession object.
582a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    RefPtrWillBeRawPtr<Event> event = Event::create(EventTypeNames::error);
583521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    event->setTarget(this);
584521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    m_asyncEventQueue->enqueueEvent(event.release());
585521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
586521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
587e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)void MediaKeySession::error(WebContentDecryptionModuleException exception, unsigned long systemCode, const WebString& errorMessage)
58876c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles){
58976c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)    WTF_LOG(Media, "MediaKeySession::error: exception=%d, systemCode=%lu", exception, systemCode);
59076c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)
59176c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)    // FIXME: EME-WD MediaKeyError now derives from DOMException. Figure out how
59276c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)    // to implement this without breaking prefixed EME, which has a totally
59376c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)    // different definition. The spec may also change to be just a DOMException.
59476c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)    // For now, simply generate an existing MediaKeyError.
59576c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)    MediaKeyErrorCode errorCode;
59676c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)    switch (exception) {
597e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    case WebContentDecryptionModuleExceptionClientError:
59876c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)        errorCode = MediaKeyErrorCodeClient;
59976c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)        break;
60076c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)    default:
60176c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)        // All other exceptions get converted into Unknown.
60276c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)        errorCode = MediaKeyErrorCodeUnknown;
60376c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)        break;
60476c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)    }
60576c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)    error(errorCode, systemCode);
60676c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)}
60776c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)
60809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)const AtomicString& MediaKeySession::interfaceName() const
609521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
61009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return EventTargetNames::MediaKeySession;
61109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
612521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
61309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)ExecutionContext* MediaKeySession::executionContext() const
61409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
61509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return ActiveDOMObject::executionContext();
616926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
617926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
61809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)bool MediaKeySession::hasPendingActivity() const
619926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
620d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // Remain around if there are pending events or MediaKeys is still around
621d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // and we're not closed.
622197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    WTF_LOG(Media, "MediaKeySession(%p)::hasPendingActivity %s%s%s%s", this,
623197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        ActiveDOMObject::hasPendingActivity() ? " ActiveDOMObject::hasPendingActivity()" : "",
624197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        !m_pendingActions.isEmpty() ? " !m_pendingActions.isEmpty()" : "",
625197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        m_asyncEventQueue->hasPendingEvents() ? " m_asyncEventQueue->hasPendingEvents()" : "",
6267242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        (m_mediaKeys && !m_isClosed) ? " m_mediaKeys && !m_isClosed" : "");
627197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
62809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return ActiveDOMObject::hasPendingActivity()
629d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        || !m_pendingActions.isEmpty()
630d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        || m_asyncEventQueue->hasPendingEvents()
6317242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        || (m_mediaKeys && !m_isClosed);
632926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
633926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
63409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void MediaKeySession::stop()
635926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
636d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // Stop the CDM from firing any more events for this session.
637d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    m_session.clear();
638d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    m_isClosed = true;
639d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
640d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (m_actionTimer.isActive())
641d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        m_actionTimer.stop();
642d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    m_pendingActions.clear();
64309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    m_asyncEventQueue->close();
644926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
645926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
646f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liuvoid MediaKeySession::trace(Visitor* visitor)
647f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu{
648197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    visitor->trace(m_error);
6495d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    visitor->trace(m_asyncEventQueue);
650197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    visitor->trace(m_pendingActions);
6517242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    visitor->trace(m_mediaKeys);
652c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    visitor->trace(m_closedPromise);
653d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    EventTargetWithInlineData::trace(visitor);
654f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu}
655f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
656e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)} // namespace blink
657