1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "media/base/cdm_promise.h"
6
7#include "base/bind.h"
8#include "base/logging.h"
9#include "base/metrics/histogram.h"
10
11namespace media {
12
13template <typename T>
14struct CdmPromiseTraits {};
15
16template <>
17struct CdmPromiseTraits<void> {
18  static const CdmPromise::ResolveParameterType kType = CdmPromise::VOID_TYPE;
19};
20
21template <>
22struct CdmPromiseTraits<std::string> {
23  static const CdmPromise::ResolveParameterType kType = CdmPromise::STRING_TYPE;
24};
25
26template <>
27struct CdmPromiseTraits<KeyIdsVector> {
28  static const CdmPromise::ResolveParameterType kType =
29      CdmPromise::KEY_IDS_VECTOR_TYPE;
30};
31
32CdmPromise::CdmPromise(ResolveParameterType parameter_type)
33    : parameter_type_(parameter_type), is_pending_(true) {
34}
35
36CdmPromise::CdmPromise(ResolveParameterType parameter_type,
37                       PromiseRejectedCB reject_cb)
38    : parameter_type_(parameter_type),
39      reject_cb_(reject_cb),
40      is_pending_(true) {
41  DCHECK(!reject_cb_.is_null());
42}
43
44CdmPromise::CdmPromise(ResolveParameterType parameter_type,
45                       PromiseRejectedCB reject_cb,
46                       const std::string& uma_name)
47    : parameter_type_(parameter_type),
48      reject_cb_(reject_cb),
49      is_pending_(true),
50      uma_name_(uma_name) {
51  DCHECK(!reject_cb_.is_null());
52  DCHECK(!uma_name_.empty());
53}
54
55CdmPromise::~CdmPromise() {
56  DCHECK(!is_pending_);
57}
58
59static CdmPromise::ResultCodeForUMA ConvertExceptionToUMAResult(
60    MediaKeys::Exception exception_code) {
61  switch (exception_code) {
62    case MediaKeys::NOT_SUPPORTED_ERROR:
63      return CdmPromise::NOT_SUPPORTED_ERROR;
64    case MediaKeys::INVALID_STATE_ERROR:
65      return CdmPromise::INVALID_STATE_ERROR;
66    case MediaKeys::INVALID_ACCESS_ERROR:
67      return CdmPromise::INVALID_ACCESS_ERROR;
68    case MediaKeys::QUOTA_EXCEEDED_ERROR:
69      return CdmPromise::QUOTA_EXCEEDED_ERROR;
70    case MediaKeys::UNKNOWN_ERROR:
71      return CdmPromise::UNKNOWN_ERROR;
72    case MediaKeys::CLIENT_ERROR:
73      return CdmPromise::CLIENT_ERROR;
74    case MediaKeys::OUTPUT_ERROR:
75      return CdmPromise::OUTPUT_ERROR;
76  }
77  NOTREACHED();
78  return CdmPromise::UNKNOWN_ERROR;
79}
80
81void CdmPromise::reject(MediaKeys::Exception exception_code,
82                        uint32 system_code,
83                        const std::string& error_message) {
84  ReportResultToUMA(ConvertExceptionToUMAResult(exception_code));
85  reject_cb_.Run(exception_code, system_code, error_message);
86}
87
88void CdmPromise::ReportResultToUMA(ResultCodeForUMA result) {
89  DCHECK(is_pending_);
90  is_pending_ = false;
91  if (!uma_name_.empty()) {
92    base::LinearHistogram::FactoryGet(
93        uma_name_,
94        1,
95        NUM_RESULT_CODES,
96        NUM_RESULT_CODES + 1,
97        base::HistogramBase::kUmaTargetedHistogramFlag)->Add(result);
98  }
99}
100
101template <typename T>
102CdmPromiseTemplate<T>::CdmPromiseTemplate(
103    base::Callback<void(const T&)> resolve_cb,
104    PromiseRejectedCB reject_cb)
105    : CdmPromise(CdmPromiseTraits<T>::kType, reject_cb),
106      resolve_cb_(resolve_cb) {
107  DCHECK(!resolve_cb_.is_null());
108}
109
110template <typename T>
111CdmPromiseTemplate<T>::CdmPromiseTemplate(
112    base::Callback<void(const T&)> resolve_cb,
113    PromiseRejectedCB reject_cb,
114    const std::string& uma_name)
115    : CdmPromise(CdmPromiseTraits<T>::kType, reject_cb, uma_name),
116      resolve_cb_(resolve_cb) {
117  DCHECK(!resolve_cb_.is_null());
118}
119
120template <typename T>
121CdmPromiseTemplate<T>::CdmPromiseTemplate()
122    : CdmPromise(CdmPromiseTraits<T>::kType) {
123}
124
125template <typename T>
126void CdmPromiseTemplate<T>::resolve(const T& result) {
127  ReportResultToUMA(SUCCESS);
128  resolve_cb_.Run(result);
129}
130
131CdmPromiseTemplate<void>::CdmPromiseTemplate(base::Callback<void()> resolve_cb,
132                                             PromiseRejectedCB reject_cb)
133    : CdmPromise(CdmPromiseTraits<void>::kType, reject_cb),
134      resolve_cb_(resolve_cb) {
135  DCHECK(!resolve_cb_.is_null());
136}
137
138CdmPromiseTemplate<void>::CdmPromiseTemplate(base::Callback<void()> resolve_cb,
139                                             PromiseRejectedCB reject_cb,
140                                             const std::string& uma_name)
141    : CdmPromise(CdmPromiseTraits<void>::kType, reject_cb, uma_name),
142      resolve_cb_(resolve_cb) {
143  DCHECK(!resolve_cb_.is_null());
144  DCHECK(!uma_name_.empty());
145}
146
147CdmPromiseTemplate<void>::CdmPromiseTemplate()
148    : CdmPromise(CdmPromiseTraits<void>::kType) {
149}
150
151void CdmPromiseTemplate<void>::resolve() {
152  ReportResultToUMA(SUCCESS);
153  resolve_cb_.Run();
154}
155
156// Explicit template instantiation for the Promises needed.
157template class MEDIA_EXPORT CdmPromiseTemplate<std::string>;
158template class MEDIA_EXPORT CdmPromiseTemplate<KeyIdsVector>;
159
160}  // namespace media
161