1 // Copyright (c) 2011 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 "chrome/renderer/plugins/plugin_uma.h"
10 #include "base/metrics/histogram.h"
11 #include "base/strings/string_util.h"
12 #include "content/public/common/content_constants.h"
13 #include "third_party/widevine/cdm/widevine_cdm_common.h"
17 // String we will use to convert mime type to plugin type.
18 const char kWindowsMediaPlayerType
[] = "application/x-mplayer2";
19 const char kSilverlightTypePrefix
[] = "application/x-silverlight";
20 const char kRealPlayerTypePrefix
[] = "audio/x-pn-realaudio";
21 const char kJavaTypeSubstring
[] = "application/x-java-applet";
22 const char kQuickTimeType
[] = "video/quicktime";
24 // Arrays containing file extensions connected with specific plugins.
25 // Note: THE ARRAYS MUST BE SORTED BECAUSE BINARY SEARCH IS USED ON THEM!
26 const char* const kWindowsMediaPlayerExtensions
[] = {".asx"};
28 const char* const kRealPlayerExtensions
[] = {".ra", ".ram", ".rm",
29 ".rmm", ".rmp", ".rpm"};
31 const char* const kQuickTimeExtensions
[] = {".moov", ".mov", ".qif",
32 ".qt", ".qti", ".qtif"};
34 const char* const kShockwaveFlashExtensions
[] = {".spl", ".swf"};
38 class UMASenderImpl
: public PluginUMAReporter::UMASender
{
39 void SendPluginUMA(PluginUMAReporter::ReportType report_type
,
40 PluginUMAReporter::PluginType plugin_type
) override
;
43 void UMASenderImpl::SendPluginUMA(PluginUMAReporter::ReportType report_type
,
44 PluginUMAReporter::PluginType plugin_type
) {
45 // UMA_HISTOGRAM_ENUMERATION requires constant histogram name. Use string
46 // constants explicitly instead of trying to use variables for names.
47 switch (report_type
) {
48 case PluginUMAReporter::MISSING_PLUGIN
:
49 UMA_HISTOGRAM_ENUMERATION("Plugin.MissingPlugins",
51 PluginUMAReporter::PLUGIN_TYPE_MAX
);
53 case PluginUMAReporter::DISABLED_PLUGIN
:
54 UMA_HISTOGRAM_ENUMERATION("Plugin.DisabledPlugins",
56 PluginUMAReporter::PLUGIN_TYPE_MAX
);
64 PluginUMAReporter
* PluginUMAReporter::GetInstance() {
65 return Singleton
<PluginUMAReporter
>::get();
68 void PluginUMAReporter::ReportPluginMissing(const std::string
& plugin_mime_type
,
69 const GURL
& plugin_src
) {
70 report_sender_
->SendPluginUMA(MISSING_PLUGIN
,
71 GetPluginType(plugin_mime_type
, plugin_src
));
74 void PluginUMAReporter::ReportPluginDisabled(
75 const std::string
& plugin_mime_type
,
76 const GURL
& plugin_src
) {
77 report_sender_
->SendPluginUMA(DISABLED_PLUGIN
,
78 GetPluginType(plugin_mime_type
, plugin_src
));
81 PluginUMAReporter::PluginUMAReporter() : report_sender_(new UMASenderImpl()) {}
83 PluginUMAReporter::~PluginUMAReporter() {}
86 bool PluginUMAReporter::CompareCStrings(const char* first
, const char* second
) {
87 return strcmp(first
, second
) < 0;
90 bool PluginUMAReporter::CStringArrayContainsCString(const char* const* array
,
93 return std::binary_search(array
, array
+ array_size
, str
, CompareCStrings
);
96 void PluginUMAReporter::ExtractFileExtension(const GURL
& src
,
97 std::string
* extension
) {
98 std::string
extension_file_path(src
.ExtractFileName());
99 if (extension_file_path
.empty())
100 extension_file_path
= src
.host();
102 size_t last_dot
= extension_file_path
.find_last_of('.');
103 if (last_dot
!= std::string::npos
) {
104 *extension
= extension_file_path
.substr(last_dot
);
109 *extension
= base::ToLowerASCII(*extension
);
112 PluginUMAReporter::PluginType
PluginUMAReporter::GetPluginType(
113 const std::string
& plugin_mime_type
,
114 const GURL
& plugin_src
) {
115 // If we know plugin's mime type, we use it to determine plugin's type. Else,
116 // we try to determine plugin type using plugin source's extension.
117 if (!plugin_mime_type
.empty())
118 return MimeTypeToPluginType(base::ToLowerASCII(plugin_mime_type
));
120 return SrcToPluginType(plugin_src
);
123 PluginUMAReporter::PluginType
PluginUMAReporter::SrcToPluginType(
125 std::string file_extension
;
126 ExtractFileExtension(src
, &file_extension
);
127 if (CStringArrayContainsCString(kWindowsMediaPlayerExtensions
,
128 arraysize(kWindowsMediaPlayerExtensions
),
129 file_extension
.c_str())) {
130 return WINDOWS_MEDIA_PLAYER
;
133 if (CStringArrayContainsCString(kQuickTimeExtensions
,
134 arraysize(kQuickTimeExtensions
),
135 file_extension
.c_str())) {
139 if (CStringArrayContainsCString(kRealPlayerExtensions
,
140 arraysize(kRealPlayerExtensions
),
141 file_extension
.c_str())) {
145 if (CStringArrayContainsCString(kShockwaveFlashExtensions
,
146 arraysize(kShockwaveFlashExtensions
),
147 file_extension
.c_str())) {
148 return SHOCKWAVE_FLASH
;
151 return UNSUPPORTED_EXTENSION
;
154 PluginUMAReporter::PluginType
PluginUMAReporter::MimeTypeToPluginType(
155 const std::string
& mime_type
) {
156 if (mime_type
== kWindowsMediaPlayerType
)
157 return WINDOWS_MEDIA_PLAYER
;
159 size_t prefix_length
= strlen(kSilverlightTypePrefix
);
160 if (strncmp(mime_type
.c_str(), kSilverlightTypePrefix
, prefix_length
) == 0)
163 prefix_length
= strlen(kRealPlayerTypePrefix
);
164 if (strncmp(mime_type
.c_str(), kRealPlayerTypePrefix
, prefix_length
) == 0)
167 if (strstr(mime_type
.c_str(), kJavaTypeSubstring
))
170 if (mime_type
== kQuickTimeType
)
173 if (mime_type
== content::kBrowserPluginMimeType
)
174 return BROWSER_PLUGIN
;
176 if (mime_type
== content::kFlashPluginSwfMimeType
||
177 mime_type
== content::kFlashPluginSplMimeType
) {
178 return SHOCKWAVE_FLASH
;
181 #if defined(ENABLE_PEPPER_CDMS)
182 if (mime_type
== kWidevineCdmPluginMimeType
)
186 return UNSUPPORTED_MIMETYPE
;