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