Home | History | Annotate | Download | only in encryptedmedia
      1 /*
      2  * Copyright (C) 2013 Apple Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
     14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
     17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     23  * THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 #include "modules/encryptedmedia/MediaKeys.h"
     28 
     29 #include "bindings/v8/ExceptionState.h"
     30 #include "core/dom/EventNames.h"
     31 #include "core/html/HTMLMediaElement.h"
     32 #include "core/platform/UUID.h"
     33 #include "core/platform/graphics/ContentDecryptionModule.h"
     34 #include "modules/encryptedmedia/MediaKeyMessageEvent.h"
     35 #include "modules/encryptedmedia/MediaKeySession.h"
     36 #include "wtf/HashSet.h"
     37 
     38 namespace WebCore {
     39 
     40 PassRefPtr<MediaKeys> MediaKeys::create(const String& keySystem, ExceptionState& es)
     41 {
     42     // From <http://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html#dom-media-keys-constructor>:
     43     // The MediaKeys(keySystem) constructor must run the following steps:
     44 
     45     // 1. If keySystem is null or an empty string, throw an InvalidAccessError exception and abort these steps.
     46     if (keySystem.isEmpty()) {
     47         es.throwDOMException(InvalidAccessError);
     48         return 0;
     49     }
     50 
     51     // 2. If keySystem is not one of the user agent's supported Key Systems, throw a NotSupportedError and abort these steps.
     52     if (!ContentDecryptionModule::supportsKeySystem(keySystem)) {
     53         es.throwDOMException(NotSupportedError);
     54         return 0;
     55     }
     56 
     57     // 3. Let cdm be the content decryption module corresponding to keySystem.
     58     // 4. Load cdm if necessary.
     59     OwnPtr<ContentDecryptionModule> cdm = ContentDecryptionModule::create(keySystem);
     60     if (!cdm) {
     61         es.throwDOMException(NotSupportedError);
     62         return 0;
     63     }
     64 
     65     // 5. Create a new MediaKeys object.
     66     // 5.1 Let the keySystem attribute be keySystem.
     67     // 6. Return the new object to the caller.
     68     return adoptRef(new MediaKeys(keySystem, cdm.release()));
     69 }
     70 
     71 MediaKeys::MediaKeys(const String& keySystem, PassOwnPtr<ContentDecryptionModule> cdm)
     72     : m_mediaElement(0)
     73     , m_keySystem(keySystem)
     74     , m_cdm(cdm)
     75 {
     76     ScriptWrappable::init(this);
     77 }
     78 
     79 MediaKeys::~MediaKeys()
     80 {
     81     // From <http://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html#dom-media-keys-constructor>:
     82     // When destroying a MediaKeys object, follow the steps in close().
     83     for (size_t i = 0; i < m_sessions.size(); ++i)
     84         m_sessions[i]->close();
     85 }
     86 
     87 PassRefPtr<MediaKeySession> MediaKeys::createSession(ScriptExecutionContext* context, const String& type, Uint8Array* initData, ExceptionState& es)
     88 {
     89     // From <http://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html#dom-createsession>:
     90     // The createSession(type, initData) method must run the following steps:
     91     // Note: The contents of initData are container-specific Initialization Data.
     92 
     93     // 1. If type is null or an empty string and initData is not null or an empty string, throw an
     94     // InvalidAccessError exception and abort these steps.
     95     if ((type.isEmpty()) && (!initData || initData->length())) {
     96         es.throwDOMException(InvalidAccessError);
     97         return 0;
     98     }
     99 
    100     // 2. If type contains a MIME type that is not supported or is not supported by the keySystem, throw
    101     // a NotSupportedError exception and abort these steps.
    102     ASSERT(!type.isEmpty());
    103     if (type.isEmpty() || !m_cdm->supportsMIMEType(type)) {
    104         es.throwDOMException(NotSupportedError);
    105         return 0;
    106     }
    107 
    108     // 3. Create a new MediaKeySession object.
    109     RefPtr<MediaKeySession> session = MediaKeySession::create(context, m_cdm.get(), this);
    110     // 3.1 Let the keySystem attribute be keySystem.
    111     ASSERT(!session->keySystem().isEmpty());
    112     // 3.2 Let the sessionId attribute be a unique Session ID string. It may be generated by cdm.
    113     // This is handled by m_cdm and may happen asynchronously.
    114 
    115     // 4. Add the new object to an internal list of session objects.
    116     m_sessions.append(session);
    117 
    118     // 5. Schedule a task to generate a key request, providing type, initData, and the new object.
    119     session->generateKeyRequest(type, initData);
    120 
    121     // 6. Return the new object to the caller.
    122     return session;
    123 }
    124 
    125 void MediaKeys::setMediaElement(HTMLMediaElement* element)
    126 {
    127     // FIXME: Cause HTMLMediaElement::setMediaKeys() to throw an exception if m_mediaElement is not 0.
    128     // FIXME: Hook up the CDM to the WebMediaPlayer in Chromium.
    129     ASSERT(!m_mediaElement);
    130     m_mediaElement = element;
    131 }
    132 
    133 }
    134