| // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/renderer/plugins/plugin_uma.h" |
| |
| #include <algorithm> |
| #include <cstring> |
| |
| #include "base/metrics/histogram.h" |
| #include "base/strings/string_util.h" |
| #include "content/public/common/content_constants.h" |
| #include "third_party/widevine/cdm/widevine_cdm_common.h" |
| |
| namespace { |
| |
| // String we will use to convert mime type to plugin type. |
| const char kWindowsMediaPlayerType[] = "application/x-mplayer2"; |
| const char kSilverlightTypePrefix[] = "application/x-silverlight"; |
| const char kRealPlayerTypePrefix[] = "audio/x-pn-realaudio"; |
| const char kJavaTypeSubstring[] = "application/x-java-applet"; |
| const char kQuickTimeType[] = "video/quicktime"; |
| |
| // Arrays containing file extensions connected with specific plugins. |
| // Note: THE ARRAYS MUST BE SORTED BECAUSE BINARY SEARCH IS USED ON THEM! |
| const char* const kWindowsMediaPlayerExtensions[] = {".asx"}; |
| |
| const char* const kRealPlayerExtensions[] = {".ra", ".ram", ".rm", |
| ".rmm", ".rmp", ".rpm"}; |
| |
| const char* const kQuickTimeExtensions[] = {".moov", ".mov", ".qif", |
| ".qt", ".qti", ".qtif"}; |
| |
| const char* const kShockwaveFlashExtensions[] = {".spl", ".swf"}; |
| |
| } // namespace. |
| |
| class UMASenderImpl : public PluginUMAReporter::UMASender { |
| void SendPluginUMA(PluginUMAReporter::ReportType report_type, |
| PluginUMAReporter::PluginType plugin_type) override; |
| }; |
| |
| void UMASenderImpl::SendPluginUMA(PluginUMAReporter::ReportType report_type, |
| PluginUMAReporter::PluginType plugin_type) { |
| // UMA_HISTOGRAM_ENUMERATION requires constant histogram name. Use string |
| // constants explicitly instead of trying to use variables for names. |
| switch (report_type) { |
| case PluginUMAReporter::MISSING_PLUGIN: |
| UMA_HISTOGRAM_ENUMERATION("Plugin.MissingPlugins", |
| plugin_type, |
| PluginUMAReporter::PLUGIN_TYPE_MAX); |
| break; |
| case PluginUMAReporter::DISABLED_PLUGIN: |
| UMA_HISTOGRAM_ENUMERATION("Plugin.DisabledPlugins", |
| plugin_type, |
| PluginUMAReporter::PLUGIN_TYPE_MAX); |
| break; |
| default: |
| NOTREACHED(); |
| } |
| } |
| |
| // static. |
| PluginUMAReporter* PluginUMAReporter::GetInstance() { |
| return base::Singleton<PluginUMAReporter>::get(); |
| } |
| |
| void PluginUMAReporter::ReportPluginMissing(const std::string& plugin_mime_type, |
| const GURL& plugin_src) { |
| report_sender_->SendPluginUMA(MISSING_PLUGIN, |
| GetPluginType(plugin_mime_type, plugin_src)); |
| } |
| |
| void PluginUMAReporter::ReportPluginDisabled( |
| const std::string& plugin_mime_type, |
| const GURL& plugin_src) { |
| report_sender_->SendPluginUMA(DISABLED_PLUGIN, |
| GetPluginType(plugin_mime_type, plugin_src)); |
| } |
| |
| PluginUMAReporter::PluginUMAReporter() : report_sender_(new UMASenderImpl()) {} |
| |
| PluginUMAReporter::~PluginUMAReporter() {} |
| |
| // static. |
| bool PluginUMAReporter::CompareCStrings(const char* first, const char* second) { |
| return strcmp(first, second) < 0; |
| } |
| |
| bool PluginUMAReporter::CStringArrayContainsCString(const char* const* array, |
| size_t array_size, |
| const char* str) { |
| return std::binary_search(array, array + array_size, str, CompareCStrings); |
| } |
| |
| void PluginUMAReporter::ExtractFileExtension(const GURL& src, |
| std::string* extension) { |
| std::string extension_file_path(src.ExtractFileName()); |
| if (extension_file_path.empty()) |
| extension_file_path = src.host(); |
| |
| size_t last_dot = extension_file_path.find_last_of('.'); |
| if (last_dot != std::string::npos) { |
| *extension = extension_file_path.substr(last_dot); |
| } else { |
| extension->clear(); |
| } |
| |
| *extension = base::ToLowerASCII(*extension); |
| } |
| |
| PluginUMAReporter::PluginType PluginUMAReporter::GetPluginType( |
| const std::string& plugin_mime_type, |
| const GURL& plugin_src) { |
| // If we know plugin's mime type, we use it to determine plugin's type. Else, |
| // we try to determine plugin type using plugin source's extension. |
| if (!plugin_mime_type.empty()) |
| return MimeTypeToPluginType(base::ToLowerASCII(plugin_mime_type)); |
| |
| return SrcToPluginType(plugin_src); |
| } |
| |
| PluginUMAReporter::PluginType PluginUMAReporter::SrcToPluginType( |
| const GURL& src) { |
| std::string file_extension; |
| ExtractFileExtension(src, &file_extension); |
| if (CStringArrayContainsCString(kWindowsMediaPlayerExtensions, |
| arraysize(kWindowsMediaPlayerExtensions), |
| file_extension.c_str())) { |
| return WINDOWS_MEDIA_PLAYER; |
| } |
| |
| if (CStringArrayContainsCString(kQuickTimeExtensions, |
| arraysize(kQuickTimeExtensions), |
| file_extension.c_str())) { |
| return QUICKTIME; |
| } |
| |
| if (CStringArrayContainsCString(kRealPlayerExtensions, |
| arraysize(kRealPlayerExtensions), |
| file_extension.c_str())) { |
| return REALPLAYER; |
| } |
| |
| if (CStringArrayContainsCString(kShockwaveFlashExtensions, |
| arraysize(kShockwaveFlashExtensions), |
| file_extension.c_str())) { |
| return SHOCKWAVE_FLASH; |
| } |
| |
| return UNSUPPORTED_EXTENSION; |
| } |
| |
| PluginUMAReporter::PluginType PluginUMAReporter::MimeTypeToPluginType( |
| const std::string& mime_type) { |
| if (mime_type == kWindowsMediaPlayerType) |
| return WINDOWS_MEDIA_PLAYER; |
| |
| size_t prefix_length = strlen(kSilverlightTypePrefix); |
| if (strncmp(mime_type.c_str(), kSilverlightTypePrefix, prefix_length) == 0) |
| return SILVERLIGHT; |
| |
| prefix_length = strlen(kRealPlayerTypePrefix); |
| if (strncmp(mime_type.c_str(), kRealPlayerTypePrefix, prefix_length) == 0) |
| return REALPLAYER; |
| |
| if (strstr(mime_type.c_str(), kJavaTypeSubstring)) |
| return JAVA; |
| |
| if (mime_type == kQuickTimeType) |
| return QUICKTIME; |
| |
| if (mime_type == content::kBrowserPluginMimeType) |
| return BROWSER_PLUGIN; |
| |
| if (mime_type == content::kFlashPluginSwfMimeType || |
| mime_type == content::kFlashPluginSplMimeType) { |
| return SHOCKWAVE_FLASH; |
| } |
| |
| #if defined(ENABLE_PEPPER_CDMS) |
| if (mime_type == kWidevineCdmPluginMimeType) |
| return WIDEVINE_CDM; |
| #endif |
| |
| return UNSUPPORTED_MIMETYPE; |
| } |