diff options
author | thakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-07 01:18:58 +0000 |
---|---|---|
committer | thakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-07 01:18:58 +0000 |
commit | cc6e701be963178587b1e6edab1c74ec025ad9c0 (patch) | |
tree | eb2b7fbfa27c75edfa563adf10f93ba855575c38 /chrome/default_plugin/plugin_database_handler.cc | |
parent | d8e0a0c7cd72ceeb3ae0675018856cf66c70e1f2 (diff) | |
download | chromium_src-cc6e701be963178587b1e6edab1c74ec025ad9c0.zip chromium_src-cc6e701be963178587b1e6edab1c74ec025ad9c0.tar.gz chromium_src-cc6e701be963178587b1e6edab1c74ec025ad9c0.tar.bz2 |
Move default_plugin out of webkit.
BUG=48419
Review URL: http://codereview.chromium.org/2803035
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@51681 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/default_plugin/plugin_database_handler.cc')
-rw-r--r-- | chrome/default_plugin/plugin_database_handler.cc | 358 |
1 files changed, 358 insertions, 0 deletions
diff --git a/chrome/default_plugin/plugin_database_handler.cc b/chrome/default_plugin/plugin_database_handler.cc new file mode 100644 index 0000000..ab79752 --- /dev/null +++ b/chrome/default_plugin/plugin_database_handler.cc @@ -0,0 +1,358 @@ +// Copyright (c) 2006-2008 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/default_plugin/plugin_database_handler.h" + +#if defined(USE_SYSTEM_LIBXML) +#include <parser.h> +#include <xpath.h> +#else +#include "third_party/libxml/include/libxml/parser.h" +#include "third_party/libxml/include/libxml/xpath.h" +#endif + +#include "base/file_util.h" +#include "base/path_service.h" +#include "base/string_util.h" +#include "base/time.h" +#include "base/utf_string_conversions.h" +#include "chrome/default_plugin/plugin_impl.h" +#include "chrome/default_plugin/plugin_main.h" + +using base::Time; +using base::TimeDelta; + +PluginDatabaseHandler::PluginDatabaseHandler( + PluginInstallerImpl& plugin_installer_instance) + : plugin_downloads_file_(INVALID_HANDLE_VALUE), + plugin_installer_instance_(plugin_installer_instance), + ignore_plugin_db_data_(false) { +} + +PluginDatabaseHandler::~PluginDatabaseHandler() { + if (plugin_downloads_file_ != INVALID_HANDLE_VALUE) { + ::CloseHandle(plugin_downloads_file_); + plugin_downloads_file_ = INVALID_HANDLE_VALUE; + } +} + +bool PluginDatabaseHandler::DownloadPluginsFileIfNeeded( + const std::string& plugin_finder_url) { + DCHECK(!plugin_finder_url.empty()); + // The time in days for which the plugins list is cached. + // TODO(iyengar) Make this configurable. + const int kPluginsListCacheTimeInDays = 3; + + plugin_finder_url_ = plugin_finder_url; + + PathService::Get(base::DIR_MODULE, &plugins_file_); + plugins_file_ += L"\\chrome_plugins_file.xml"; + + bool initiate_download = false; + if (!file_util::PathExists(FilePath::FromWStringHack(plugins_file_))) { + initiate_download = true; + } else { + SYSTEMTIME creation_system_time = {0}; + if (!file_util::GetFileCreationLocalTime(plugins_file_, + &creation_system_time)) { + NOTREACHED(); + return false; + } + + FILETIME creation_file_time = {0}; + ::SystemTimeToFileTime(&creation_system_time, &creation_file_time); + + FILETIME current_time = {0}; + ::GetSystemTimeAsFileTime(¤t_time); + + Time file_time = Time::FromFileTime(creation_file_time); + Time current_system_time = Time::FromFileTime(current_time); + + TimeDelta time_diff = file_time - current_system_time; + if (time_diff.InDays() > kPluginsListCacheTimeInDays) { + initiate_download = true; + } + } + + if (initiate_download) { + DLOG(INFO) << "Initiating GetURLNotify on the plugin finder URL " + << plugin_finder_url.c_str(); + + plugin_installer_instance_.set_plugin_installer_state( + PluginListDownloadInitiated); + + DCHECK(default_plugin::g_browser->geturlnotify); + default_plugin::g_browser->geturlnotify( + plugin_installer_instance_.instance(), plugin_finder_url.c_str(), + NULL, NULL); + } else { + DLOG(INFO) << "Plugins file " << plugins_file_.c_str() + << " already exists"; + plugin_downloads_file_ = ::CreateFile(plugins_file_.c_str(), GENERIC_READ, + FILE_SHARE_READ, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + if (plugin_downloads_file_ == INVALID_HANDLE_VALUE) { + DLOG(INFO) << "Failed to open plugins file " + << plugins_file_.c_str() << " Error " + << ::GetLastError(); + NOTREACHED(); + return false; + } + // The URLNotify function contains all handling needed to parse the plugins + // file and display the UI accordingly. + plugin_installer_instance_.set_plugin_installer_state( + PluginListDownloadInitiated); + plugin_installer_instance_.URLNotify(plugin_finder_url.c_str(), + NPRES_DONE); + } + return true; +} + +int32 PluginDatabaseHandler::Write(NPStream* stream, int32 offset, + int32 buffer_length, void* buffer) { + if (ignore_plugin_db_data_) { + return buffer_length; + } + + if (plugin_downloads_file_ == INVALID_HANDLE_VALUE) { + DLOG(INFO) << "About to create plugins file " << plugins_file_.c_str(); + plugin_downloads_file_ = CreateFile(plugins_file_.c_str(), + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ, NULL, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, NULL); + if (plugin_downloads_file_ == INVALID_HANDLE_VALUE) { + unsigned long error = ::GetLastError(); + if (error == ERROR_SHARING_VIOLATION) { + // File may have been downloaded by another plugin instance on this + // page. + plugin_downloads_file_ = ::CreateFile( + plugins_file_.c_str(), GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + if (plugin_downloads_file_ != INVALID_HANDLE_VALUE) { + ignore_plugin_db_data_ = true; + return buffer_length; + } + } + + DLOG(INFO) << "Failed to create plugins file " + << plugins_file_.c_str() << " Error " + << ::GetLastError(); + NOTREACHED(); + return 0; + } + } + + DWORD bytes_written = 0; + if (0 == lstrcmpiA(stream->url, plugin_finder_url_.c_str())) { + DCHECK(plugin_downloads_file_ != INVALID_HANDLE_VALUE); + + WriteFile(plugin_downloads_file_, buffer, buffer_length, &bytes_written, + NULL); + DCHECK_EQ(buffer_length, static_cast<int32>(bytes_written)); + } + return bytes_written; +} + + +bool PluginDatabaseHandler::ParsePluginList() { + if (plugin_downloads_file_ == INVALID_HANDLE_VALUE) { + DLOG(WARNING) << "Invalid plugins file"; + NOTREACHED(); + return false; + } + + bool parse_result = false; + + std::string plugins_file = WideToUTF8(plugins_file_.c_str()); + xmlDocPtr plugin_downloads_doc = xmlParseFile(plugins_file.c_str()); + if (plugin_downloads_doc == NULL) { + DLOG(WARNING) << "Failed to parse plugins file " << plugins_file.c_str(); + return parse_result; + } + + xmlXPathContextPtr context = NULL; + xmlXPathObjectPtr plugins_result = NULL; + + do { + context = xmlXPathNewContext(plugin_downloads_doc); + if (context == NULL) { + DLOG(WARNING) << "Failed to retrieve XPath context"; + NOTREACHED(); + parse_result = false; + break; + } + + plugins_result = + xmlXPathEvalExpression(reinterpret_cast<const xmlChar*>("//plugin"), + context); + if ((plugins_result == NULL) || + xmlXPathNodeSetIsEmpty(plugins_result->nodesetval)) { + DLOG(WARNING) << "Failed to find XPath //plugin"; + NOTREACHED(); + parse_result = false; + break; + } + + xmlNodeSetPtr plugin_list = plugins_result->nodesetval; + for (int plugin_index = 0; plugin_index < plugin_list->nodeNr; + ++plugin_index) { + PluginDetail plugin_detail; + if (!ReadPluginInfo(plugin_list->nodeTab[plugin_index]->children, + &plugin_detail)) { + DLOG(ERROR) << "Failed to read plugin details at index " + << plugin_index; + break; + } + downloaded_plugins_list_.push_back(plugin_detail); + } + if (downloaded_plugins_list_.size()) + parse_result = true; + } while (0); + + xmlXPathFreeContext(context); + xmlXPathFreeObject(plugins_result); + xmlFreeDoc(plugin_downloads_doc); + xmlCleanupParser(); + DLOG(INFO) << "Parse plugins file result " << parse_result; + return parse_result; +} + +bool PluginDatabaseHandler::GetPluginDetailsForMimeType( + const char* mime_type, const char* language, + std::string* download_url, std::wstring* plugin_name, + bool* download_url_for_display) { + if (!mime_type || !language || !download_url || !plugin_name || + !download_url_for_display) { + NOTREACHED(); + return false; + } + + PluginList::iterator plugin_index; + for (plugin_index = downloaded_plugins_list_.begin(); + plugin_index != downloaded_plugins_list_.end(); + ++plugin_index) { + PluginDetail& current_plugin = *plugin_index; + + std::vector<std::string>::iterator mime_type_index; + for (mime_type_index = current_plugin.mime_types.begin(); + mime_type_index != current_plugin.mime_types.end(); + ++mime_type_index) { + if ((0 == lstrcmpiA(mime_type, (*mime_type_index).c_str())) && + (0 == lstrcmpiA(language, current_plugin.language.c_str()))) { + *download_url = current_plugin.download_url; + *plugin_name = current_plugin.display_name; + *download_url_for_display = current_plugin.download_url_for_display; + return true; + } + } + } + return false; +} + +void PluginDatabaseHandler::Close(bool delete_file) { + if (plugin_downloads_file_ != INVALID_HANDLE_VALUE) { + ::CloseHandle(plugin_downloads_file_); + plugin_downloads_file_ = INVALID_HANDLE_VALUE; + if (delete_file) { + ::DeleteFile(plugins_file_.c_str()); + plugins_file_.clear(); + } + } +} + +bool PluginDatabaseHandler::ReadPluginInfo(_xmlNode* plugin_node, + PluginDetail* plugin_detail) { + static const char kMimeTypeSeparator = ';'; + + if (!plugin_node) { + NOTREACHED(); + return false; + } + + _xmlNode* plugin_mime_type = plugin_node->next; + if ((plugin_mime_type == NULL) || + (plugin_mime_type->next == NULL)) { + DLOG(WARNING) << "Failed to find mime type node in file"; + NOTREACHED(); + return false; + } + _xmlNode* plugin_mime_type_vals = plugin_mime_type->children; + if (plugin_mime_type_vals == NULL) { + DLOG(WARNING) << "Invalid mime type"; + NOTREACHED(); + return false; + } + // Skip the first child of each node as it is the text element + // for that node. + _xmlNode* plugin_lang_node = plugin_mime_type->next->next; + if ((plugin_lang_node == NULL) || + (plugin_lang_node->next == NULL)) { + DLOG(WARNING) << "Failed to find plugin language node"; + NOTREACHED(); + return false; + } + _xmlNode* plugin_lang_val = plugin_lang_node->children; + if (plugin_lang_val == NULL) { + DLOG(WARNING) << "Invalid plugin language"; + NOTREACHED(); + return false; + } + _xmlNode* plugin_name_node = plugin_lang_node->next->next; + if ((plugin_name_node == NULL) || + (plugin_name_node->next == NULL)) { + DLOG(WARNING) << "Failed to find plugin name node"; + NOTREACHED(); + return false; + } + _xmlNode* plugin_name_val = plugin_name_node->children; + if (plugin_name_val == NULL) { + DLOG(WARNING) << "Invalid plugin name"; + NOTREACHED(); + return false; + } + _xmlNode* plugin_download_url_node = plugin_name_node->next->next; + if (plugin_download_url_node == NULL) { + DLOG(WARNING) << "Failed to find plugin URL node"; + NOTREACHED(); + return false; + } + _xmlNode* plugin_download_url_val = plugin_download_url_node->children; + if (plugin_download_url_val == NULL) { + DLOG(WARNING) << "Invalid plugin URL"; + NOTREACHED(); + return false; + } + + // Look for the DisplayUrl node. By default every URL is treated as an + // executable URL. + plugin_detail->download_url_for_display = false; + + _xmlNode* plugin_download_url_for_display_node = + plugin_download_url_node->next->next; + if (plugin_download_url_for_display_node) { + _xmlNode* url_for_display_val = + plugin_download_url_for_display_node->children; + if (url_for_display_val) { + int url_for_display = 0; + StringToInt(reinterpret_cast<const char*>(url_for_display_val->content), + &url_for_display); + if (url_for_display != 0) + plugin_detail->download_url_for_display = true; + } + } + + plugin_detail->display_name = + UTF8ToWide(reinterpret_cast<const char*>(plugin_name_val->content)); + plugin_detail->download_url = + reinterpret_cast<const char*>(plugin_download_url_val->content); + + SplitString(reinterpret_cast<const char*>(plugin_mime_type_vals->content), + kMimeTypeSeparator, &plugin_detail->mime_types); + + plugin_detail->language = + reinterpret_cast<const char*>(plugin_lang_val->content); + + return true; +} |