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 base::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(base::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