• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "chrome/renderer/plugins/plugin_uma.h"
6 
7 #include <algorithm>
8 #include <cstring>
9 
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"
14 
15 namespace {
16 
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";
23 
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* kWindowsMediaPlayerExtensions[] = {".asx"};
27 
28 const char* kRealPlayerExtensions[] = {".ra",  ".ram", ".rm",
29                                        ".rmm", ".rmp", ".rpm"};
30 
31 const char* kQuickTimeExtensions[] = {".moov", ".mov", ".qif",
32                                       ".qt",   ".qti", ".qtif"};
33 
34 const char* kShockwaveFlashExtensions[] = {".spl", ".swf"};
35 
36 }  // namespace.
37 
38 class UMASenderImpl : public PluginUMAReporter::UMASender {
39   virtual void SendPluginUMA(
40       PluginUMAReporter::ReportType report_type,
41       PluginUMAReporter::PluginType plugin_type) OVERRIDE;
42 };
43 
SendPluginUMA(PluginUMAReporter::ReportType report_type,PluginUMAReporter::PluginType plugin_type)44 void UMASenderImpl::SendPluginUMA(PluginUMAReporter::ReportType report_type,
45                                   PluginUMAReporter::PluginType plugin_type) {
46   // UMA_HISTOGRAM_ENUMERATION requires constant histogram name. Use string
47   // constants explicitly instead of trying to use variables for names.
48   switch (report_type) {
49     case PluginUMAReporter::MISSING_PLUGIN:
50       UMA_HISTOGRAM_ENUMERATION("Plugin.MissingPlugins",
51                                 plugin_type,
52                                 PluginUMAReporter::PLUGIN_TYPE_MAX);
53       break;
54     case PluginUMAReporter::DISABLED_PLUGIN:
55       UMA_HISTOGRAM_ENUMERATION("Plugin.DisabledPlugins",
56                                 plugin_type,
57                                 PluginUMAReporter::PLUGIN_TYPE_MAX);
58       break;
59     default:
60       NOTREACHED();
61   }
62 }
63 
64 // static.
GetInstance()65 PluginUMAReporter* PluginUMAReporter::GetInstance() {
66   return Singleton<PluginUMAReporter>::get();
67 }
68 
ReportPluginMissing(const std::string & plugin_mime_type,const GURL & plugin_src)69 void PluginUMAReporter::ReportPluginMissing(const std::string& plugin_mime_type,
70                                             const GURL& plugin_src) {
71   report_sender_->SendPluginUMA(MISSING_PLUGIN,
72                                 GetPluginType(plugin_mime_type, plugin_src));
73 }
74 
ReportPluginDisabled(const std::string & plugin_mime_type,const GURL & plugin_src)75 void PluginUMAReporter::ReportPluginDisabled(
76     const std::string& plugin_mime_type,
77     const GURL& plugin_src) {
78   report_sender_->SendPluginUMA(DISABLED_PLUGIN,
79                                 GetPluginType(plugin_mime_type, plugin_src));
80 }
81 
PluginUMAReporter()82 PluginUMAReporter::PluginUMAReporter() : report_sender_(new UMASenderImpl()) {}
83 
~PluginUMAReporter()84 PluginUMAReporter::~PluginUMAReporter() {}
85 
86 // static.
CompareCStrings(const char * first,const char * second)87 bool PluginUMAReporter::CompareCStrings(const char* first, const char* second) {
88   return strcmp(first, second) < 0;
89 }
90 
CStringArrayContainsCString(const char ** array,size_t array_size,const char * str)91 bool PluginUMAReporter::CStringArrayContainsCString(const char** array,
92                                                     size_t array_size,
93                                                     const char* str) {
94   return std::binary_search(array, array + array_size, str, CompareCStrings);
95 }
96 
ExtractFileExtension(const GURL & src,std::string * extension)97 void PluginUMAReporter::ExtractFileExtension(const GURL& src,
98                                              std::string* extension) {
99   std::string extension_file_path(src.ExtractFileName());
100   if (extension_file_path.empty())
101     extension_file_path = src.host();
102 
103   size_t last_dot = extension_file_path.find_last_of('.');
104   if (last_dot != std::string::npos) {
105     *extension = extension_file_path.substr(last_dot);
106   } else {
107     extension->clear();
108   }
109 
110   base::StringToLowerASCII(extension);
111 }
112 
GetPluginType(const std::string & plugin_mime_type,const GURL & plugin_src)113 PluginUMAReporter::PluginType PluginUMAReporter::GetPluginType(
114     const std::string& plugin_mime_type,
115     const GURL& plugin_src) {
116   // If we know plugin's mime type, we use it to determine plugin's type. Else,
117   // we try to determine plugin type using plugin source's extension.
118   if (!plugin_mime_type.empty())
119     return MimeTypeToPluginType(base::StringToLowerASCII(plugin_mime_type));
120 
121   return SrcToPluginType(plugin_src);
122 }
123 
SrcToPluginType(const GURL & src)124 PluginUMAReporter::PluginType PluginUMAReporter::SrcToPluginType(
125     const GURL& src) {
126   std::string file_extension;
127   ExtractFileExtension(src, &file_extension);
128   if (CStringArrayContainsCString(kWindowsMediaPlayerExtensions,
129                                   arraysize(kWindowsMediaPlayerExtensions),
130                                   file_extension.c_str())) {
131     return WINDOWS_MEDIA_PLAYER;
132   }
133 
134   if (CStringArrayContainsCString(kQuickTimeExtensions,
135                                   arraysize(kQuickTimeExtensions),
136                                   file_extension.c_str())) {
137     return QUICKTIME;
138   }
139 
140   if (CStringArrayContainsCString(kRealPlayerExtensions,
141                                   arraysize(kRealPlayerExtensions),
142                                   file_extension.c_str())) {
143     return REALPLAYER;
144   }
145 
146   if (CStringArrayContainsCString(kShockwaveFlashExtensions,
147                                   arraysize(kShockwaveFlashExtensions),
148                                   file_extension.c_str())) {
149     return SHOCKWAVE_FLASH;
150   }
151 
152   return UNSUPPORTED_EXTENSION;
153 }
154 
MimeTypeToPluginType(const std::string & mime_type)155 PluginUMAReporter::PluginType PluginUMAReporter::MimeTypeToPluginType(
156     const std::string& mime_type) {
157   if (mime_type == kWindowsMediaPlayerType)
158     return WINDOWS_MEDIA_PLAYER;
159 
160   size_t prefix_length = strlen(kSilverlightTypePrefix);
161   if (strncmp(mime_type.c_str(), kSilverlightTypePrefix, prefix_length) == 0)
162     return SILVERLIGHT;
163 
164   prefix_length = strlen(kRealPlayerTypePrefix);
165   if (strncmp(mime_type.c_str(), kRealPlayerTypePrefix, prefix_length) == 0)
166     return REALPLAYER;
167 
168   if (strstr(mime_type.c_str(), kJavaTypeSubstring))
169     return JAVA;
170 
171   if (mime_type == kQuickTimeType)
172     return QUICKTIME;
173 
174   if (mime_type == content::kBrowserPluginMimeType)
175     return BROWSER_PLUGIN;
176 
177   if (mime_type == content::kFlashPluginSwfMimeType ||
178       mime_type == content::kFlashPluginSplMimeType) {
179     return SHOCKWAVE_FLASH;
180   }
181 
182 #if defined(ENABLE_PEPPER_CDMS)
183   if (mime_type == kWidevineCdmPluginMimeType)
184     return WIDEVINE_CDM;
185 #endif
186 
187   return UNSUPPORTED_MIMETYPE;
188 }
189