Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / media / cdm / ppapi / external_clear_key / clear_key_cdm.cc
index 9cdd9c3..64e0158 100644 (file)
@@ -5,6 +5,7 @@
 #include "media/cdm/ppapi/external_clear_key/clear_key_cdm.h"
 
 #include <algorithm>
+#include <cstring>
 #include <sstream>
 #include <string>
 #include <vector>
@@ -15,6 +16,7 @@
 #include "base/time/time.h"
 #include "media/base/decoder_buffer.h"
 #include "media/base/decrypt_config.h"
+#include "media/cdm/json_web_key.h"
 #include "media/cdm/ppapi/cdm_file_io_test.h"
 #include "media/cdm/ppapi/external_clear_key/cdm_video_decoder.h"
 
@@ -69,6 +71,16 @@ const char kExternalClearKeyFileIOTestKeySystem[] =
 const char kExternalClearKeyCrashKeySystem[] =
     "org.chromium.externalclearkey.crash";
 
+// Constants for the enumalted session that can be loaded by LoadSession().
+// These constants need to be in sync with
+// chrome/test/data/media/encrypted_media_utils.js
+const char kLoadableWebSessionId[] = "LoadableSession";
+const char kLoadableSessionContentType[] = "video/webm";
+const uint8 kLoadableSessionKeyId[] = "0123456789012345";
+const uint8 kLoadableSessionKey[] =
+    {0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, 0xd2, 0x7b,
+     0x68, 0xef, 0x12, 0x2a, 0xfc, 0xe4, 0xae, 0x3c};
+
 const int64 kSecondsPerMinute = 60;
 const int64 kMsPerSecond = 1000;
 const int64 kInitialTimerDelayMs = 200;
@@ -183,8 +195,9 @@ ClearKeyCdm::ClearKeyCdm(ClearKeyCdmHost* host, const std::string& key_system)
       host_(host),
       key_system_(key_system),
       last_session_id_(MediaKeys::kInvalidSessionId),
+      session_id_for_emulated_loadsession_(MediaKeys::kInvalidSessionId),
       timer_delay_ms_(kInitialTimerDelayMs),
-      timer_set_(false) {
+      heartbeat_timer_set_(false) {
 #if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER)
   channel_count_ = 0;
   bits_per_channel_ = 0;
@@ -212,15 +225,35 @@ void ClearKeyCdm::CreateSession(uint32 session_id,
     StartFileIOTest();
 }
 
+// Loads a emulated stored session. Currently only |kLoadableWebSessionId|
+// (containing a |kLoadableSessionKey| for |kLoadableSessionKeyId|) is
+// supported.
+void ClearKeyCdm::LoadSession(uint32_t session_id,
+                              const char* web_session_id,
+                              uint32_t web_session_id_length) {
+  DVLOG(1) << __FUNCTION__;
+
+  if (std::string(kLoadableWebSessionId) !=
+      std::string(web_session_id, web_session_id_length)) {
+    // TODO(xhwang): Report "NotFoundError" when we support DOMError style.
+    OnSessionError(session_id, MediaKeys::kUnknownError, 0);
+    return;
+  }
+
+  session_id_for_emulated_loadsession_ = session_id;
+
+  decryptor_.CreateSession(session_id, kLoadableSessionContentType, NULL, 0);
+}
+
 void ClearKeyCdm::UpdateSession(uint32 session_id,
                                 const uint8* response,
                                 uint32 response_size) {
   DVLOG(1) << __FUNCTION__;
   decryptor_.UpdateSession(session_id, response, response_size);
 
-  if (!timer_set_) {
+  if (!heartbeat_timer_set_) {
     ScheduleNextHeartBeat();
-    timer_set_ = true;
+    heartbeat_timer_set_ = true;
   }
 }
 
@@ -230,6 +263,12 @@ void ClearKeyCdm::ReleaseSession(uint32 session_id) {
 }
 
 void ClearKeyCdm::TimerExpired(void* context) {
+  if (context == &session_id_for_emulated_loadsession_) {
+    LoadLoadableSession();
+    return;
+  }
+
+  DCHECK(heartbeat_timer_set_);
   std::string heartbeat_message;
   if (!next_heartbeat_message_.empty() &&
       context == &next_heartbeat_message_[0]) {
@@ -489,8 +528,34 @@ void ClearKeyCdm::OnQueryOutputProtectionStatus(
   NOTIMPLEMENTED();
 };
 
+void ClearKeyCdm::LoadLoadableSession() {
+  std::string jwk_set = GenerateJWKSet(kLoadableSessionKey,
+                                       sizeof(kLoadableSessionKey),
+                                       kLoadableSessionKeyId,
+                                       sizeof(kLoadableSessionKeyId) - 1);
+  // TODO(xhwang): This triggers OnSessionUpdated(). For prefixed EME support,
+  // this is okay. Check WD EME support.
+  decryptor_.UpdateSession(session_id_for_emulated_loadsession_,
+                           reinterpret_cast<const uint8*>(jwk_set.data()),
+                           jwk_set.size());
+}
+
 void ClearKeyCdm::OnSessionCreated(uint32 session_id,
                                    const std::string& web_session_id) {
+  std::string new_web_session_id = web_session_id;
+
+  if (session_id == session_id_for_emulated_loadsession_) {
+    // Delay LoadLoadableSession() to test the case where Decrypt*() calls are
+    // made before the session is fully loaded.
+    const int64 kDelayToLoadSessionMs = 500;
+    // Use the address of |session_id_for_emulated_loadsession_| as the timer
+    // context so that we can call LoadLoadableSession() when the timer expires.
+    host_->SetTimer(kDelayToLoadSessionMs,
+                    &session_id_for_emulated_loadsession_);
+    // Defer OnSessionCreated() until the session is loaded.
+    return;
+  }
+
   host_->OnSessionCreated(
       session_id, web_session_id.data(), web_session_id.size());
 }
@@ -498,6 +563,12 @@ void ClearKeyCdm::OnSessionCreated(uint32 session_id,
 void ClearKeyCdm::OnSessionMessage(uint32 session_id,
                                    const std::vector<uint8>& message,
                                    const std::string& destination_url) {
+  DVLOG(1) << "OnSessionMessage: " << message.size();
+
+  // Ignore the message when we are waiting to update the loadable session.
+  if (session_id == session_id_for_emulated_loadsession_)
+    return;
+
   host_->OnSessionMessage(session_id,
                           reinterpret_cast<const char*>(message.data()),
                           message.size(),
@@ -506,6 +577,12 @@ void ClearKeyCdm::OnSessionMessage(uint32 session_id,
 }
 
 void ClearKeyCdm::OnSessionReady(uint32 session_id) {
+  if (session_id == session_id_for_emulated_loadsession_) {
+    session_id_for_emulated_loadsession_ = MediaKeys::kInvalidSessionId;
+    host_->OnSessionCreated(
+        session_id, kLoadableWebSessionId, strlen(kLoadableWebSessionId));
+  }
+
   host_->OnSessionReady(session_id);
 }