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[] = {".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 
     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.
     65 PluginUMAReporter* PluginUMAReporter::GetInstance() {
     66   return Singleton<PluginUMAReporter>::get();
     67 }
     68 
     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 
     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 
     82 PluginUMAReporter::PluginUMAReporter() : report_sender_(new UMASenderImpl()) {}
     83 
     84 PluginUMAReporter::~PluginUMAReporter() {}
     85 
     86 // static.
     87 bool PluginUMAReporter::CompareCStrings(const char* first, const char* second) {
     88   return strcmp(first, second) < 0;
     89 }
     90 
     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 
     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   StringToLowerASCII(extension);
    111 }
    112 
    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(StringToLowerASCII(plugin_mime_type));
    120 
    121   return SrcToPluginType(plugin_src);
    122 }
    123 
    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 
    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