plugin_uma.cc revision 4e180b6a0b4720a9b8e9e959a882386f690f08ff
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
15namespace {
16
17// String we will use to convert mime type to plugin type.
18const char kWindowsMediaPlayerType[] = "application/x-mplayer2";
19const char kSilverlightTypePrefix[] = "application/x-silverlight";
20const char kRealPlayerTypePrefix[] = "audio/x-pn-realaudio";
21const char kJavaTypeSubstring[] = "application/x-java-applet";
22const 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!
26const char* kWindowsMediaPlayerExtensions[] = {".asx"};
27
28const char* kRealPlayerExtensions[] = {".ra",  ".ram", ".rm",
29                                       ".rmm", ".rmp", ".rpm"};
30
31const char* kQuickTimeExtensions[] = {".moov", ".mov", ".qif",
32                                      ".qt",   ".qti", ".qtif"};
33
34const char* kShockwaveFlashExtensions[] = {".spl", ".swf"};
35
36}  // namespace.
37
38class UMASenderImpl : public PluginUMAReporter::UMASender {
39  virtual void SendPluginUMA(
40      PluginUMAReporter::ReportType report_type,
41      PluginUMAReporter::PluginType plugin_type) OVERRIDE;
42};
43
44void 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.
65PluginUMAReporter* PluginUMAReporter::GetInstance() {
66  return Singleton<PluginUMAReporter>::get();
67}
68
69void 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
75void 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
82PluginUMAReporter::PluginUMAReporter() : report_sender_(new UMASenderImpl()) {}
83
84PluginUMAReporter::~PluginUMAReporter() {}
85
86// static.
87bool PluginUMAReporter::CompareCStrings(const char* first, const char* second) {
88  return strcmp(first, second) < 0;
89}
90
91bool 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
97void 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  StringToLowerASCII(extension);
111}
112
113PluginUMAReporter::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(StringToLowerASCII(plugin_mime_type));
120
121  return SrcToPluginType(plugin_src);
122}
123
124PluginUMAReporter::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
155PluginUMAReporter::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