Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / media / blink / webmediaplayer_util.cc
blob5a794b0211bbb1170143dca582cd8e5d614e52b3
1 // Copyright 2013 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.
5 #include "media/blink/webmediaplayer_util.h"
7 #include <math.h>
9 #include "base/metrics/histogram.h"
10 #include "media/base/bind_to_current_loop.h"
11 #include "media/base/media_client.h"
12 #include "media/base/media_keys.h"
13 #include "third_party/WebKit/public/platform/WebMediaPlayerEncryptedMediaClient.h"
15 namespace media {
17 // Compile asserts shared by all platforms.
19 #define STATIC_ASSERT_MATCHING_ENUM(name) \
20 static_assert(static_cast<int>(blink::WebMediaPlayerEncryptedMediaClient:: \
21 MediaKeyErrorCode##name) == \
22 static_cast<int>(MediaKeys::k##name##Error), \
23 "mismatching enum values: " #name)
24 STATIC_ASSERT_MATCHING_ENUM(Unknown);
25 STATIC_ASSERT_MATCHING_ENUM(Client);
26 #undef STATIC_ASSERT_MATCHING_ENUM
28 base::TimeDelta ConvertSecondsToTimestamp(double seconds) {
29 double microseconds = seconds * base::Time::kMicrosecondsPerSecond;
30 return base::TimeDelta::FromMicroseconds(
31 microseconds > 0 ? microseconds + 0.5 : ceil(microseconds - 0.5));
34 blink::WebTimeRanges ConvertToWebTimeRanges(
35 const Ranges<base::TimeDelta>& ranges) {
36 blink::WebTimeRanges result(ranges.size());
37 for (size_t i = 0; i < ranges.size(); ++i) {
38 result[i].start = ranges.start(i).InSecondsF();
39 result[i].end = ranges.end(i).InSecondsF();
41 return result;
44 blink::WebMediaPlayer::NetworkState PipelineErrorToNetworkState(
45 PipelineStatus error) {
46 DCHECK_NE(error, PIPELINE_OK);
48 switch (error) {
49 case PIPELINE_ERROR_NETWORK:
50 case PIPELINE_ERROR_READ:
51 return blink::WebMediaPlayer::NetworkStateNetworkError;
53 // TODO(vrk): Because OnPipelineInitialize() directly reports the
54 // NetworkStateFormatError instead of calling OnPipelineError(), I believe
55 // this block can be deleted. Should look into it! (crbug.com/126070)
56 case PIPELINE_ERROR_INITIALIZATION_FAILED:
57 case PIPELINE_ERROR_COULD_NOT_RENDER:
58 case PIPELINE_ERROR_URL_NOT_FOUND:
59 case DEMUXER_ERROR_COULD_NOT_OPEN:
60 case DEMUXER_ERROR_COULD_NOT_PARSE:
61 case DEMUXER_ERROR_NO_SUPPORTED_STREAMS:
62 case DECODER_ERROR_NOT_SUPPORTED:
63 return blink::WebMediaPlayer::NetworkStateFormatError;
65 case PIPELINE_ERROR_DECODE:
66 case PIPELINE_ERROR_ABORT:
67 case PIPELINE_ERROR_OPERATION_PENDING:
68 case PIPELINE_ERROR_INVALID_STATE:
69 return blink::WebMediaPlayer::NetworkStateDecodeError;
71 case PIPELINE_OK:
72 NOTREACHED() << "Unexpected status! " << error;
74 return blink::WebMediaPlayer::NetworkStateFormatError;
77 namespace {
79 // Helper enum for reporting scheme histograms.
80 enum URLSchemeForHistogram {
81 kUnknownURLScheme,
82 kMissingURLScheme,
83 kHttpURLScheme,
84 kHttpsURLScheme,
85 kFtpURLScheme,
86 kChromeExtensionURLScheme,
87 kJavascriptURLScheme,
88 kFileURLScheme,
89 kBlobURLScheme,
90 kDataURLScheme,
91 kFileSystemScheme,
92 kMaxURLScheme = kFileSystemScheme // Must be equal to highest enum value.
95 URLSchemeForHistogram URLScheme(const GURL& url) {
96 if (!url.has_scheme()) return kMissingURLScheme;
97 if (url.SchemeIs("http")) return kHttpURLScheme;
98 if (url.SchemeIs("https")) return kHttpsURLScheme;
99 if (url.SchemeIs("ftp")) return kFtpURLScheme;
100 if (url.SchemeIs("chrome-extension")) return kChromeExtensionURLScheme;
101 if (url.SchemeIs("javascript")) return kJavascriptURLScheme;
102 if (url.SchemeIs("file")) return kFileURLScheme;
103 if (url.SchemeIs("blob")) return kBlobURLScheme;
104 if (url.SchemeIs("data")) return kDataURLScheme;
105 if (url.SchemeIs("filesystem")) return kFileSystemScheme;
107 return kUnknownURLScheme;
110 std::string LoadTypeToString(blink::WebMediaPlayer::LoadType load_type) {
111 switch (load_type) {
112 case blink::WebMediaPlayer::LoadTypeURL:
113 return "SRC";
114 case blink::WebMediaPlayer::LoadTypeMediaSource:
115 return "MSE";
116 case blink::WebMediaPlayer::LoadTypeMediaStream:
117 return "MS";
120 NOTREACHED();
121 return "Unknown";
124 } // namespace
126 // TODO(xhwang): Call this from WebMediaPlayerMS to report metrics for
127 // MediaStream as well.
128 void ReportMetrics(blink::WebMediaPlayer::LoadType load_type,
129 const GURL& url,
130 const GURL& origin_url) {
131 // Report URL scheme, such as http, https, file, blob etc.
132 UMA_HISTOGRAM_ENUMERATION("Media.URLScheme", URLScheme(url),
133 kMaxURLScheme + 1);
135 // Keep track if this is a MSE or non-MSE playback.
136 // TODO(xhwang): This name is not intuitive. We should have a histogram for
137 // all load types.
138 UMA_HISTOGRAM_BOOLEAN(
139 "Media.MSE.Playback",
140 load_type == blink::WebMediaPlayer::LoadTypeMediaSource);
142 // Report the origin from where the media player is created.
143 if (GetMediaClient()) {
144 GetMediaClient()->RecordRapporURL(
145 "Media.OriginUrl." + LoadTypeToString(load_type), origin_url);
149 void RecordOriginOfHLSPlayback(const GURL& origin_url) {
150 if (media::GetMediaClient())
151 GetMediaClient()->RecordRapporURL("Media.OriginUrl.HLS", origin_url);
154 EmeInitDataType ConvertToEmeInitDataType(
155 blink::WebEncryptedMediaInitDataType init_data_type) {
156 switch (init_data_type) {
157 case blink::WebEncryptedMediaInitDataType::Webm:
158 return EmeInitDataType::WEBM;
159 case blink::WebEncryptedMediaInitDataType::Cenc:
160 return EmeInitDataType::CENC;
161 case blink::WebEncryptedMediaInitDataType::Keyids:
162 return EmeInitDataType::KEYIDS;
163 case blink::WebEncryptedMediaInitDataType::Unknown:
164 return EmeInitDataType::UNKNOWN;
167 NOTREACHED();
168 return EmeInitDataType::UNKNOWN;
171 blink::WebEncryptedMediaInitDataType ConvertToWebInitDataType(
172 EmeInitDataType init_data_type) {
173 switch (init_data_type) {
174 case EmeInitDataType::WEBM:
175 return blink::WebEncryptedMediaInitDataType::Webm;
176 case EmeInitDataType::CENC:
177 return blink::WebEncryptedMediaInitDataType::Cenc;
178 case EmeInitDataType::KEYIDS:
179 return blink::WebEncryptedMediaInitDataType::Keyids;
180 case EmeInitDataType::UNKNOWN:
181 return blink::WebEncryptedMediaInitDataType::Unknown;
184 NOTREACHED();
185 return blink::WebEncryptedMediaInitDataType::Unknown;
188 namespace {
189 // This class wraps a scoped WebSetSinkIdCB pointer such that
190 // copying objects of this class actually performs moving, thus
191 // maintaining clear ownership of the WebSetSinkIdCB pointer.
192 // The rationale for this class is that the SwichOutputDevice method
193 // can make a copy of its base::Callback parameter, which implies
194 // copying its bound parameters.
195 // SwitchOutputDevice actually wants to move its base::Callback
196 // parameter since only the final copy will be run, but base::Callback
197 // does not support move semantics and there is no base::MovableCallback.
198 // Since scoped pointers are not copyable, we cannot bind them directly
199 // to a base::Callback in this case. Thus, we use this helper class,
200 // whose copy constructor transfers ownership of the scoped pointer.
202 class SetSinkIdCallback {
203 public:
204 explicit SetSinkIdCallback(WebSetSinkIdCB* web_callback)
205 : web_callback_(web_callback) {}
206 SetSinkIdCallback(const SetSinkIdCallback& other)
207 : web_callback_(other.web_callback_.Pass()) {}
208 ~SetSinkIdCallback() {}
209 friend void RunSetSinkIdCallback(const SetSinkIdCallback& callback,
210 SwitchOutputDeviceResult result);
212 private:
213 // Mutable is required so that Pass() can be called in the copy
214 // constructor.
215 mutable scoped_ptr<WebSetSinkIdCB> web_callback_;
218 void RunSetSinkIdCallback(const SetSinkIdCallback& callback,
219 SwitchOutputDeviceResult result) {
220 DVLOG(1) << __FUNCTION__;
221 if (!callback.web_callback_)
222 return;
224 switch (result) {
225 case SWITCH_OUTPUT_DEVICE_RESULT_SUCCESS:
226 callback.web_callback_->onSuccess();
227 break;
228 case SWITCH_OUTPUT_DEVICE_RESULT_ERROR_NOT_FOUND:
229 callback.web_callback_->onError(new blink::WebSetSinkIdError(
230 blink::WebSetSinkIdError::ErrorTypeNotFound, "Device not found"));
231 break;
232 case SWITCH_OUTPUT_DEVICE_RESULT_ERROR_NOT_AUTHORIZED:
233 callback.web_callback_->onError(new blink::WebSetSinkIdError(
234 blink::WebSetSinkIdError::ErrorTypeSecurity,
235 "No permission to access device"));
236 break;
237 case SWITCH_OUTPUT_DEVICE_RESULT_ERROR_OBSOLETE:
238 callback.web_callback_->onError(new blink::WebSetSinkIdError(
239 blink::WebSetSinkIdError::ErrorTypeAbort,
240 "The requested operation became obsolete and was aborted"));
241 break;
242 case SWITCH_OUTPUT_DEVICE_RESULT_ERROR_NOT_SUPPORTED:
243 callback.web_callback_->onError(new blink::WebSetSinkIdError(
244 blink::WebSetSinkIdError::ErrorTypeAbort,
245 "The requested operation cannot be performed and was aborted"));
246 break;
247 default:
248 NOTREACHED();
251 callback.web_callback_ = nullptr;
254 } // namespace
256 SwitchOutputDeviceCB ConvertToSwitchOutputDeviceCB(
257 WebSetSinkIdCB* web_callbacks) {
258 return media::BindToCurrentLoop(
259 base::Bind(RunSetSinkIdCallback, SetSinkIdCallback(web_callbacks)));
262 } // namespace media