diff options
author | viettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-24 00:21:34 +0000 |
---|---|---|
committer | viettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-24 00:21:34 +0000 |
commit | cec1b8d4524bd0ce53a7b08b4263c788a5b6d72b (patch) | |
tree | c229241e080953f2ff84966f1e969747b6129268 | |
parent | 50d8766af20bd48bce1094039153291e31c0e0bf (diff) | |
download | chromium_src-cec1b8d4524bd0ce53a7b08b4263c788a5b6d72b.zip chromium_src-cec1b8d4524bd0ce53a7b08b4263c788a5b6d72b.tar.gz chromium_src-cec1b8d4524bd0ce53a7b08b4263c788a5b6d72b.tar.bz2 |
Implement chrome://plugins page that can disable plugins.
BUG=736
TEST=Go to chrome://plugins/. Should be able to enable/disable plugins. Enabled/disabled plugins should persist between sessions.
Review URL: http://codereview.chromium.org/1085003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@42412 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/app/generated_resources.grd | 41 | ||||
-rw-r--r-- | chrome/browser/browser_main.cc | 6 | ||||
-rw-r--r-- | chrome/browser/browser_prefs.cc | 2 | ||||
-rw-r--r-- | chrome/browser/browser_resources.grd | 1 | ||||
-rw-r--r-- | chrome/browser/dom_ui/dom_ui_factory.cc | 8 | ||||
-rw-r--r-- | chrome/browser/dom_ui/plugins_ui.cc | 276 | ||||
-rw-r--r-- | chrome/browser/dom_ui/plugins_ui.h | 24 | ||||
-rw-r--r-- | chrome/browser/plugin_service.cc | 34 | ||||
-rw-r--r-- | chrome/browser/plugin_service.h | 7 | ||||
-rw-r--r-- | chrome/browser/renderer_host/resource_message_filter.cc | 2 | ||||
-rw-r--r-- | chrome/browser/resources/plugins.html | 558 | ||||
-rwxr-xr-x | chrome/chrome_browser.gypi | 2 | ||||
-rw-r--r-- | chrome/common/pref_names.cc | 29 | ||||
-rw-r--r-- | chrome/common/pref_names.h | 1 | ||||
-rw-r--r-- | chrome/common/url_constants.cc | 4 | ||||
-rw-r--r-- | chrome/common/url_constants.h | 4 | ||||
-rw-r--r-- | webkit/glue/plugins/plugin_lib_mac.mm | 2 | ||||
-rw-r--r-- | webkit/glue/plugins/plugin_lib_posix.cc | 1 | ||||
-rw-r--r-- | webkit/glue/plugins/plugin_list.cc | 78 | ||||
-rw-r--r-- | webkit/glue/plugins/plugin_list.h | 22 | ||||
-rw-r--r-- | webkit/glue/webplugininfo.h | 3 |
21 files changed, 1080 insertions, 25 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 59a7674..201dc9e 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -3460,6 +3460,47 @@ Keep your key file in a safe place. You will need it to create new versions of y Allow </message> + <!-- chrome://plugins page --> + <message name="IDS_PLUGINS_TITLE" desc="Title for the chrome://plugins page."> + Plug-ins + </message> + <message name="IDS_PLUGINS_DETAILS_MODE_LINK" desc="Text of the link for details mode."> + Details + </message> + <message name="IDS_PLUGINS_NONE_INSTALLED" desc="Text that lets the user know that no plug-ins are installed."> + No plug-ins installed. + </message> + <message name="IDS_PLUGINS_DISABLED_PLUGIN" desc="Text that signifies that the plug-in is currently disabled."> + (Disabled) + </message> + <message name="IDS_PLUGINS_VERSION" desc="The label in front of a plug-in version number."> + Version: + </message> + <message name="IDS_PLUGINS_DESCRIPTION" desc="The label in front of a plug-in description."> + Description: + </message> + <message name="IDS_PLUGINS_PATH" desc="The label in front of a plug-in path (file/location on disk)."> + Location: + </message> + <message name="IDS_PLUGINS_MIME_TYPES" desc="The label in front of a plug-in's MIME types table."> + MIME types: + </message> + <message name="IDS_PLUGINS_MIME_TYPES_MIME_TYPE" desc="The label over the MIME type column in a plug-in's MIME types table."> + MIME type + </message> + <message name="IDS_PLUGINS_MIME_TYPES_DESCRIPTION" desc="The label over the description column in a plug-in's MIME types table."> + Description + </message> + <message name="IDS_PLUGINS_MIME_TYPES_FILE_EXTENSIONS" desc="The label over the file extensions column in a plug-in's MIME types table."> + File extensions + </message> + <message name="IDS_PLUGINS_DISABLE" desc="The link for disabling a plug-in."> + Disable + </message> + <message name="IDS_PLUGINS_ENABLE" desc="The link for enabling a plug-in."> + Enable + </message> + <!-- Session Crashed Info Bar--> <message name="IDS_SESSION_CRASHED_VIEW_RESTORE_BUTTON" desc="Title of the restore button in the session crashed view."> Restore diff --git a/chrome/browser/browser_main.cc b/chrome/browser/browser_main.cc index 48ecfbb..4cc4d91 100644 --- a/chrome/browser/browser_main.cc +++ b/chrome/browser/browser_main.cc @@ -45,6 +45,7 @@ #include "chrome/browser/plugin_service.h" #include "chrome/browser/pref_service.h" #include "chrome/browser/process_singleton.h" +#include "chrome/browser/profile.h" #include "chrome/browser/profile_manager.h" #include "chrome/browser/renderer_host/resource_dispatcher_host.h" #include "chrome/browser/shell_integration.h" @@ -107,7 +108,6 @@ #include "chrome/browser/browser_trial.h" #include "chrome/browser/metrics/user_metrics.h" #include "chrome/browser/net/url_fixer_upper.h" -#include "chrome/browser/profile.h" #include "chrome/browser/rlz/rlz.h" #include "chrome/browser/views/user_data_dir_dialog.h" #include "chrome/common/env_vars.h" @@ -976,8 +976,8 @@ int BrowserMain(const MainFunctionParams& parameters) { browser_process->google_url_tracker(); browser_process->intranet_redirect_detector(); - // Have Chrome plugins write their data to the profile directory. - PluginService::GetInstance()->SetChromePluginDataDir(profile->GetPath()); + // Do initialize the plug-in service (and related preferences). + PluginService::InitGlobalInstance(profile); // Prepare for memory caching of SDCH dictionaries. // Perform A/B test to measure global impact of SDCH support. diff --git a/chrome/browser/browser_prefs.cc b/chrome/browser/browser_prefs.cc index 187201a..12d626d 100644 --- a/chrome/browser/browser_prefs.cc +++ b/chrome/browser/browser_prefs.cc @@ -11,6 +11,7 @@ #include "chrome/browser/cookie_modal_dialog.h" #include "chrome/browser/debugger/devtools_manager.h" #include "chrome/browser/dom_ui/new_tab_ui.h" +#include "chrome/browser/dom_ui/plugins_ui.h" #include "chrome/browser/download/download_manager.h" #include "chrome/browser/extensions/extension_dom_ui.h" #include "chrome/browser/extensions/extension_prefs.h" @@ -97,6 +98,7 @@ void RegisterUserPrefs(PrefService* user_prefs) { ExtensionDOMUI::RegisterUserPrefs(user_prefs); ExtensionsUI::RegisterUserPrefs(user_prefs); NewTabUI::RegisterUserPrefs(user_prefs); + PluginsUI::RegisterUserPrefs(user_prefs); HostContentSettingsMap::RegisterUserPrefs(user_prefs); HostZoomMap::RegisterUserPrefs(user_prefs); DevToolsManager::RegisterUserPrefs(user_prefs); diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index 2562a2c..64127cb 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd @@ -52,6 +52,7 @@ without changes to the corresponding grd file. fbt1 --> <include name="IDR_EXTENSION_DEFAULT_ICON" file="resources\extension_default_icon.png" type="BINDATA" /> <include name="IDR_EXTENSIONS_INFOBAR_CSS" file="resources\extensions_infobar.css" flattenhtml="true" type="BINDATA" /> <include name="IDR_EXTENSIONS_TOOLSTRIP_THEME_CSS" file="resources\extensions_toolstrip.css" flattenhtml="true" type="BINDATA" /> + <include name="IDR_PLUGINS_HTML" file="resources\plugins.html" flattenhtml="true" type="BINDATA" /> <include name="IDR_PRINT_TAB_HTML" file="resources\print_tab.html" flattenhtml="true" type="BINDATA" /> <include name="IDR_PRINT_TAB_CSS" file="resources\print_tab.css" type="BINDATA" /> <include name="IDR_PRINT_TAB_JS" file="resources\print_tab.js" type="BINDATA" /> diff --git a/chrome/browser/dom_ui/dom_ui_factory.cc b/chrome/browser/dom_ui/dom_ui_factory.cc index c6fb306..01148d0 100644 --- a/chrome/browser/dom_ui/dom_ui_factory.cc +++ b/chrome/browser/dom_ui/dom_ui_factory.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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. @@ -14,6 +14,7 @@ #include "chrome/browser/dom_ui/mediaplayer_ui.h" #include "chrome/browser/dom_ui/net_internals_ui.h" #include "chrome/browser/dom_ui/new_tab_ui.h" +#include "chrome/browser/dom_ui/plugins_ui.h" #include "chrome/browser/dom_ui/print_ui.h" #include "chrome/browser/extensions/extension_dom_ui.h" #include "chrome/browser/extensions/extensions_service.h" @@ -99,6 +100,8 @@ static DOMUIFactoryFunction GetDOMUIFactoryFunction(const GURL& url) { return &NewDOMUI<HistoryUI>; if (url.host() == chrome::kChromeUINetInternalsHost) return &NewDOMUI<NetInternalsUI>; + if (url.host() == chrome::kChromeUIPluginsHost) + return &NewDOMUI<PluginsUI>; #if defined(OS_CHROMEOS) if (url.host() == chrome::kChromeUIFileBrowseHost) @@ -160,5 +163,8 @@ RefCountedMemory* DOMUIFactory::GetFaviconResourceBytes(Profile* profile, if (page_url.host() == chrome::kChromeUIHistoryHost) return HistoryUI::GetFaviconResourceBytes(); + if (page_url.host() == chrome::kChromeUIPluginsHost) + return PluginsUI::GetFaviconResourceBytes(); + return NULL; } diff --git a/chrome/browser/dom_ui/plugins_ui.cc b/chrome/browser/dom_ui/plugins_ui.cc new file mode 100644 index 0000000..948907d --- /dev/null +++ b/chrome/browser/dom_ui/plugins_ui.cc @@ -0,0 +1,276 @@ +// Copyright (c) 2010 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/browser/dom_ui/plugins_ui.h" + +#include "app/l10n_util.h" +#include "app/resource_bundle.h" +#include "base/singleton.h" +#include "base/values.h" +#include "chrome/browser/chrome_thread.h" +#include "chrome/browser/dom_ui/chrome_url_data_manager.h" +#include "chrome/browser/pref_service.h" +#include "chrome/browser/profile.h" +#include "chrome/common/jstemplate_builder.h" +#include "chrome/common/pref_names.h" +#include "chrome/common/url_constants.h" +#include "grit/browser_resources.h" +#include "grit/generated_resources.h" +#include "grit/theme_resources.h" +#include "webkit/glue/plugins/plugin_list.h" + +namespace { + +/////////////////////////////////////////////////////////////////////////////// +// +// PluginsHTMLSource +// +/////////////////////////////////////////////////////////////////////////////// + +class PluginsUIHTMLSource : public ChromeURLDataManager::DataSource { + public: + PluginsUIHTMLSource() + : DataSource(chrome::kChromeUIPluginsHost, MessageLoop::current()) {} + + // Called when the network layer has requested a resource underneath + // the path we registered. + virtual void StartDataRequest(const std::string& path, + bool is_off_the_record, + int request_id); + virtual std::string GetMimeType(const std::string&) const { + return "text/html"; + } + + private: + ~PluginsUIHTMLSource() {} + + DISALLOW_COPY_AND_ASSIGN(PluginsUIHTMLSource); +}; + +void PluginsUIHTMLSource::StartDataRequest(const std::string& path, + bool is_off_the_record, int request_id) { + // Strings used in the JsTemplate file. + DictionaryValue localized_strings; + localized_strings.SetString(L"pluginsTitle", + l10n_util::GetString(IDS_PLUGINS_TITLE)); + localized_strings.SetString(L"pluginsDetailsModeLink", + l10n_util::GetString(IDS_PLUGINS_DETAILS_MODE_LINK)); + localized_strings.SetString(L"pluginsNoneInstalled", + l10n_util::GetString(IDS_PLUGINS_NONE_INSTALLED)); + localized_strings.SetString(L"pluginDisabled", + l10n_util::GetString(IDS_PLUGINS_DISABLED_PLUGIN)); + localized_strings.SetString(L"pluginVersion", + l10n_util::GetString(IDS_PLUGINS_VERSION)); + localized_strings.SetString(L"pluginDescription", + l10n_util::GetString(IDS_PLUGINS_DESCRIPTION)); + localized_strings.SetString(L"pluginPath", + l10n_util::GetString(IDS_PLUGINS_PATH)); + localized_strings.SetString(L"pluginMimeTypes", + l10n_util::GetString(IDS_PLUGINS_MIME_TYPES)); + localized_strings.SetString(L"pluginMimeTypesMimeType", + l10n_util::GetString(IDS_PLUGINS_MIME_TYPES_MIME_TYPE)); + localized_strings.SetString(L"pluginMimeTypesDescription", + l10n_util::GetString(IDS_PLUGINS_MIME_TYPES_DESCRIPTION)); + localized_strings.SetString(L"pluginMimeTypesFileExtensions", + l10n_util::GetString(IDS_PLUGINS_MIME_TYPES_FILE_EXTENSIONS)); + localized_strings.SetString(L"disable", + l10n_util::GetString(IDS_PLUGINS_DISABLE)); + localized_strings.SetString(L"enable", + l10n_util::GetString(IDS_PLUGINS_ENABLE)); + + ChromeURLDataManager::DataSource::SetFontAndTextDirection(&localized_strings); + + static const base::StringPiece plugins_html( + ResourceBundle::GetSharedInstance().GetRawDataResource(IDR_PLUGINS_HTML)); + std::string full_html(plugins_html.data(), plugins_html.size()); + jstemplate_builder::AppendJsonHtml(&localized_strings, &full_html); + jstemplate_builder::AppendI18nTemplateSourceHtml(&full_html); + jstemplate_builder::AppendI18nTemplateProcessHtml(&full_html); + jstemplate_builder::AppendJsTemplateSourceHtml(&full_html); + + scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes); + html_bytes->data.resize(full_html.size()); + std::copy(full_html.begin(), full_html.end(), html_bytes->data.begin()); + + SendResponse(request_id, html_bytes); +} + +//////////////////////////////////////////////////////////////////////////////// +// +// PluginsDOMHandler +// +//////////////////////////////////////////////////////////////////////////////// + +// The handler for Javascript messages related to the "history" view. +// TODO(viettrungluu): Make plugin list updates notify, and then observe +// changes; maybe replumb plugin list through plugin service? +// <http://crbug.com/39101> +class PluginsDOMHandler : public DOMMessageHandler { + public: + PluginsDOMHandler() {} + virtual ~PluginsDOMHandler() {} + + // DOMMessageHandler implementation. + virtual void RegisterMessages(); + + // Callback for the "requestPluginsData" message. + void HandleRequestPluginsData(const Value* value); + + // Callback for the "enablePlugin" message. + void HandleEnablePluginMessage(const Value* value); + + private: + // Creates a dictionary containing all the information about the given plugin; + // this is put into the list to "return" for the "requestPluginsData" message. + DictionaryValue* CreatePluginDetailValue(const WebPluginInfo& plugin); + + // Creates a dictionary containing the important parts of the information + // about the given plugin; this is put into a list and saved in prefs. + DictionaryValue* CreatePluginSummaryValue(const WebPluginInfo& plugin); + + // Update the user preferences to reflect the current (user-selected) state of + // plugins. + void UpdatePreferences(); + + DISALLOW_COPY_AND_ASSIGN(PluginsDOMHandler); +}; + +void PluginsDOMHandler::RegisterMessages() { + dom_ui_->RegisterMessageCallback("requestPluginsData", + NewCallback(this, &PluginsDOMHandler::HandleRequestPluginsData)); + dom_ui_->RegisterMessageCallback("enablePlugin", + NewCallback(this, &PluginsDOMHandler::HandleEnablePluginMessage)); +} + +void PluginsDOMHandler::HandleRequestPluginsData(const Value* value) { + DictionaryValue* results = new DictionaryValue(); + + // Add plugins to the results structure. + ListValue* plugins_list = new ListValue(); + + std::vector<WebPluginInfo> plugins; + NPAPI::PluginList::Singleton()->GetPlugins(false, &plugins); + + for (std::vector<WebPluginInfo>::const_iterator it = plugins.begin(); + it != plugins.end(); + ++it) { + plugins_list->Append(CreatePluginDetailValue(*it)); + } + results->Set(L"plugins", plugins_list); + + dom_ui_->CallJavascriptFunction(L"returnPluginsData", *results); +} + +void PluginsDOMHandler::HandleEnablePluginMessage(const Value* value) { + CHECK(value->IsType(Value::TYPE_LIST)); + const ListValue* list = static_cast<const ListValue*>(value); + CHECK(list->GetSize() == 2); + FilePath::StringType plugin_path; + std::string enable_str; + CHECK(list->GetString(0, &plugin_path)); + CHECK(list->GetString(1, &enable_str)); + if (enable_str == "true") + NPAPI::PluginList::Singleton()->EnablePlugin(FilePath(plugin_path)); + else + NPAPI::PluginList::Singleton()->DisablePlugin(FilePath(plugin_path)); + + // TODO(viettrungluu): It's morally wrong to do this here (it should be done + // by the plugins service), and we might also want to ensure that the plugins + // list is always written to prefs even when the user hasn't disabled a + // plugin. This will require refactoring the plugin list and service. + // <http://crbug.com/39101> + UpdatePreferences(); +} + +DictionaryValue* PluginsDOMHandler::CreatePluginDetailValue( + const WebPluginInfo& plugin) { + DictionaryValue* plugin_data = new DictionaryValue(); + plugin_data->SetString(L"path", plugin.path.value()); + plugin_data->SetString(L"name", plugin.name); + plugin_data->SetString(L"version", plugin.version); + plugin_data->SetString(L"description", plugin.desc); + plugin_data->SetBoolean(L"enabled", plugin.enabled); + + ListValue* mime_types = new ListValue(); + for (std::vector<WebPluginMimeType>::const_iterator type_it = + plugin.mime_types.begin(); + type_it != plugin.mime_types.end(); + ++type_it) { + DictionaryValue* mime_type = new DictionaryValue(); + mime_type->SetString(L"mimeType", type_it->mime_type); + mime_type->SetString(L"description", type_it->description); + + ListValue* file_extensions = new ListValue(); + for (std::vector<std::string>::const_iterator ext_it = + type_it->file_extensions.begin(); + ext_it != type_it->file_extensions.end(); + ++ext_it) { + file_extensions->Append(new StringValue(*ext_it)); + } + mime_type->Set(L"fileExtensions", file_extensions); + + mime_types->Append(mime_type); + } + plugin_data->Set(L"mimeTypes", mime_types); + + return plugin_data; +} + +DictionaryValue* PluginsDOMHandler::CreatePluginSummaryValue( + const WebPluginInfo& plugin) { + DictionaryValue* plugin_data = new DictionaryValue(); + plugin_data->SetString(L"path", plugin.path.value()); + plugin_data->SetString(L"name", plugin.name); + plugin_data->SetString(L"version", plugin.version); + plugin_data->SetBoolean(L"enabled", plugin.enabled); + return plugin_data; +} + +void PluginsDOMHandler::UpdatePreferences() { + ListValue* plugins_list = dom_ui_->GetProfile()->GetPrefs()->GetMutableList( + prefs::kPluginsPluginsList); + plugins_list->Clear(); + + std::vector<WebPluginInfo> plugins; + NPAPI::PluginList::Singleton()->GetPlugins(false, &plugins); + + for (std::vector<WebPluginInfo>::const_iterator it = plugins.begin(); + it != plugins.end(); + ++it) { + plugins_list->Append(CreatePluginSummaryValue(*it)); + } +} + +} // namespace + +/////////////////////////////////////////////////////////////////////////////// +// +// PluginsUI +// +/////////////////////////////////////////////////////////////////////////////// + +PluginsUI::PluginsUI(TabContents* contents) : DOMUI(contents) { + AddMessageHandler((new PluginsDOMHandler())->Attach(this)); + + PluginsUIHTMLSource* html_source = new PluginsUIHTMLSource(); + + // Set up the chrome://plugins/ source. + ChromeThread::PostTask( + ChromeThread::IO, FROM_HERE, + NewRunnableMethod(Singleton<ChromeURLDataManager>::get(), + &ChromeURLDataManager::AddDataSource, + make_scoped_refptr(html_source))); +} + + +// static +RefCountedMemory* PluginsUI::GetFaviconResourceBytes() { + return ResourceBundle::GetSharedInstance(). + LoadDataResourceBytes(IDR_PLUGIN); +} + +// static +void PluginsUI::RegisterUserPrefs(PrefService* prefs) { + prefs->RegisterListPref(prefs::kPluginsPluginsList); +} diff --git a/chrome/browser/dom_ui/plugins_ui.h b/chrome/browser/dom_ui/plugins_ui.h new file mode 100644 index 0000000..00dbce9 --- /dev/null +++ b/chrome/browser/dom_ui/plugins_ui.h @@ -0,0 +1,24 @@ +// Copyright (c) 2010 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. + +#ifndef CHROME_BROWSER_DOM_UI_PLUGINS_UI_H_ +#define CHROME_BROWSER_DOM_UI_PLUGINS_UI_H_ + +#include "chrome/browser/dom_ui/dom_ui.h" + +class PrefService; +class RefCountedMemory; + +class PluginsUI : public DOMUI { + public: + explicit PluginsUI(TabContents* contents); + + static RefCountedMemory* GetFaviconResourceBytes(); + static void RegisterUserPrefs(PrefService* prefs); + + private: + DISALLOW_COPY_AND_ASSIGN(PluginsUI); +}; + +#endif // CHROME_BROWSER_DOM_UI_PLUGINS_UI_H_ diff --git a/chrome/browser/plugin_service.cc b/chrome/browser/plugin_service.cc index 987d68e..12a15e1 100644 --- a/chrome/browser/plugin_service.cc +++ b/chrome/browser/plugin_service.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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. @@ -10,12 +10,15 @@ #include "base/path_service.h" #include "base/string_util.h" #include "base/thread.h" +#include "base/values.h" #include "base/waitable_event.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_plugin_host.h" #include "chrome/browser/chrome_thread.h" #include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/plugin_process_host.h" +#include "chrome/browser/pref_service.h" +#include "chrome/browser/profile.h" #include "chrome/browser/renderer_host/render_process_host.h" #include "chrome/common/chrome_plugin_lib.h" #include "chrome/common/chrome_paths.h" @@ -25,6 +28,7 @@ #include "chrome/common/logging_chrome.h" #include "chrome/common/notification_type.h" #include "chrome/common/notification_service.h" +#include "chrome/common/pref_names.h" #include "chrome/common/render_messages.h" #ifndef DISABLE_NACL #include "native_client/src/trusted/plugin/nacl_entry_points.h" @@ -48,6 +52,34 @@ static void NotifyPluginsOfActivation() { bool PluginService::enable_chrome_plugins_ = true; // static +void PluginService::InitGlobalInstance(Profile* profile) { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); + + // Disable plugins listed as disabled in prefs. + if (const ListValue* saved_plugins_list = + profile->GetPrefs()->GetList(prefs::kPluginsPluginsList)) { + for (ListValue::const_iterator it = saved_plugins_list->begin(); + it != saved_plugins_list->end(); + ++it) { + if (!(*it)->IsType(Value::TYPE_DICTIONARY)) { + LOG(WARNING) << "Invalid entry in " << prefs::kPluginsPluginsList; + continue; // Oops, don't know what to do with this item. + } + + DictionaryValue* plugin = static_cast<DictionaryValue*>(*it); + FilePath::StringType path; + bool enabled = true; + plugin->GetBoolean(L"enabled", &enabled); + if (!enabled && plugin->GetString(L"path", &path)) + NPAPI::PluginList::Singleton()->DisablePlugin(FilePath(path)); + } + } + + // Have Chrome plugins write their data to the profile directory. + GetInstance()->SetChromePluginDataDir(profile->GetPath()); +} + +// static PluginService* PluginService::GetInstance() { return Singleton<PluginService>::get(); } diff --git a/chrome/browser/plugin_service.h b/chrome/browser/plugin_service.h index 7ab39e2..f3214e0 100644 --- a/chrome/browser/plugin_service.h +++ b/chrome/browser/plugin_service.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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. @@ -31,6 +31,7 @@ class Message; class MessageLoop; class PluginProcessHost; +class Profile; class URLRequestContext; class ResourceDispatcherHost; class ResourceMessageFilter; @@ -41,6 +42,10 @@ class PluginService : public base::WaitableEventWatcher::Delegate, public NotificationObserver { public: + // Initializes the global instance; should be called on startup from the main + // thread. + static void InitGlobalInstance(Profile* profile); + // Returns the PluginService singleton. static PluginService* GetInstance(); diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc index 74ae523..48c1cb6 100644 --- a/chrome/browser/renderer_host/resource_message_filter.cc +++ b/chrome/browser/renderer_host/resource_message_filter.cc @@ -746,7 +746,7 @@ void ResourceMessageFilter::OnGetPluginsOnFileThread( bool refresh, IPC::Message* reply_msg) { DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); std::vector<WebPluginInfo> plugins; - NPAPI::PluginList::Singleton()->GetPlugins(refresh, &plugins); + NPAPI::PluginList::Singleton()->GetEnabledPlugins(refresh, &plugins); ViewHostMsg_GetPlugins::WriteReplyParams(reply_msg, plugins); ChromeThread::PostTask( ChromeThread::IO, FROM_HERE, diff --git a/chrome/browser/resources/plugins.html b/chrome/browser/resources/plugins.html new file mode 100644 index 0000000..19cbedb --- /dev/null +++ b/chrome/browser/resources/plugins.html @@ -0,0 +1,558 @@ +<!DOCTYPE HTML> +<html i18n-values="dir:textdirection;"> +<head> +<meta charset="utf-8"> +<title i18n-content="pluginsTitle"></title> +<style> + +body { + margin: 10px; + min-width: 47em; +} + +a { + color: blue; + font-size: 103%; +} + +div#header { + margin-bottom: 1.05em; + overflow: hidden; + padding-bottom: 1.5em; + padding-left: 0; + padding-top: 1.5em; + position: relative; +} + +html[dir='rtl'] div#header { + padding-right: 0; +} + +div#header h1 { + background: url('../../app/theme/extensions_section.png') 0px 20px no-repeat; + display: inline; + margin: 0; + padding-bottom: 43px; + padding-left: 75px; + padding-top: 40px; +} + +html[dir='rtl'] div#header h1 { + background: url('../../app/theme/extensions_section.png') right no-repeat; + padding-right: 95px; + padding-left: 0; +} + +h1 { + font-size: 156%; + font-weight: bold; + padding: 0; + margin: 0; +} + +div.content { + font-size: 88%; + margin-top: 5px; +} + +.section-header { + background: #ebeff9; + border-top: 1px solid #b5c7de; + font-size: 99%; + padding-bottom: 2px; + padding-left: 5px; + padding-top: 3px; + width: 100%; +} + +html[dir='rtl'] .section-header { + padding-right: 5px; + padding-left: 0; +} + +.section-header > table tr td:first-child { + width: 100%; +} + +.section-header > table { + width: 100%; +} + +.section-header-title { + font-weight: bold; +} + +.vbox-container { + display: -webkit-box; + -webkit-box-orient: vertical; +} + +.wbox { + display: -webkit-box; + -webkit-box-align: stretch; + -webkit-box-flex: 1; +} + +.wbox#top { + padding-right: 5px; +} + +html[dir='rtl'] .wbox#top { + padding-left: 5px; + padding-right: 0; +} + +.showInTmiMode { + overflow: hidden; +} + +body.hideTmiModeInitial .showInTmiMode { + height: 0 !important; + opacity: 0; +} + +body.hideTmiMode .showInTmiMode { + height: 0 !important; + opacity: 0; + -webkit-transition: all .1s ease-out; +} + +body.showTmiModeInitial .showInTmiMode { + opacity: 1; +} + +body.showTmiMode .showInTmiMode { + opacity: 1; + -webkit-transition: all .1s ease-in; +} + +.wbox-tmi-mode { + -webkit-box-align: stretch; + -webkit-box-flex: 1; +} + +.tmi-mode-image { + margin-top: 2px; + padding-left: 5px; + padding-right: 5px; +} + +.tmi-mode-link { + margin-right: 3px; + white-space: nowrap; +} + +.tmi-mode-link a { + font-size: 97%; +} + +.tmi-mode { + background: #f4f6fc; + border-bottom: 1px solid #edeff5; + font-size: 89%; + padding-bottom: 0.8em; + padding-left: 10px; + padding-top: 0.8em; + width: 100%; +} + +html[dir='rtl'] .tmi-mode { + padding-right: 10px; + padding-left: 0; +} + +.plugin_disabled > td { + background: url('gray.png') 0px 0px; + color: #a0a0a0; + padding-bottom: 4px; + padding-top: 5px; +} + +.plugin_enabled > td { + padding-bottom: 4px; + padding-top: 5px; +} + +.plugin { + border-bottom: 1px solid #cdcdcd; +} + +/* Indent the text related to each plug-in. */ +.plugin-text { + padding-left: 5px; +} + +html[dir='rtl'] .plugin-text { + padding-right: 5px; + padding-left: 0; +} + +.plugin-name { + font-weight: bold; +} + +.no-plugins { + margin: 6em 0 0; + text-align: center; + font-size: 1.2em; +} + +/* Use tables for layout, so eliminate extra spacing. */ +.plugin-details table { + -webkit-border-horizontal-spacing: 0; + -webkit-border-vertical-spacing: 0; +} + +/* Separate the inital line, Description, Location, and MIME Types lines. */ +.plugin-details > div { + padding-top: 0.1em +} + +/* Align rows of tables along the top. */ +.plugin-details tr { + vertical-align: top; +} + +/* Separate columns by 1em for the most part. */ +.plugin-details td+td { + padding-left: 1em; +} + +html[dir='rtl'] .plugin-details td+td { + padding-right: 1em; + padding-left: 0; +} + +/* Make the MIME Types tables smaller. */ +.plugin-details .mime_types { + font-size: 95%; +} + +/* Separate the header from the contents in each MIME Types table. */ +.plugin-details .mime_types .header td { + padding-bottom: 0.1em; + border-bottom: 1px solid; +} + +/* Separate the columns for tables used for horizontal listings only a bit. */ +.hlisting td+td { + padding-left: 0.4em; +} + +html[dir='rtl'] .hlisting td+td { + padding-right: 0.4em; + padding-left: 0; +} + +/* Match the indentation of .plugin-text. */ +.plugin-actions { + padding-left: 5px; + margin-top: 0.2em; + margin-bottom: 0.2em; +} + +html[dir='rtl'] .plugin-actions { + padding-right: 5px; + padding-left: 0; +} + +button { + font-size: 104%; +} + +</style> +<script> + +/** + * This variable structure is here to document the structure that the template + * expects to correctly populate the page. + */ +var pluginDataFormat = { + 'plugins': [ + { + 'path': '/blahblah/blahblah/MyCrappyPlugin.plugin', + 'name': 'MyCrappyPlugin', + 'version': '1.2.3', + 'description': 'My crappy plugin', + 'mimeTypes': [ + { 'description': 'Foo Media', + 'fileExtensions': [ 'foo' ], + 'mimeType': 'application/x-my-foo' }, + { 'description': 'Bar Stuff', + 'fileExtensions': [ 'bar','baz' ], + 'mimeType': 'application/my-bar' } + ], + 'enabled': true + }, + { + 'path': '/foobar/baz/YourGreatPlugin.plugin', + 'name': 'YourGreatPlugin', + 'version': '4.5', + 'description': 'Your great plugin', + 'mimeTypes': [ + { 'description': 'Baz Stuff', + 'fileExtensions': [ 'baz' ], + 'mimeType': 'application/x-your-baz' } + ], + 'enabled': false + } + ] +}; + +/** + * Takes the |pluginsData| input argument which represents data about the + * currently installed/running plugins and populates the html jstemplate with + * that data. It expects an object structure like the above. + * @param {Object} pluginsData Detailed info about installed plugins + */ +function renderTemplate(pluginsData) { + // This is the javascript code that processes the template: + var input = new JsEvalContext(pluginsData); + var output = document.getElementById('pluginTemplate'); + jstProcess(input, output); +} + +/** + * Asks the C++ PluginsDOMHandler to get details about the installed plugins and + * return detailed data about the configuration. The PluginsDOMHandler should + * reply to returnPluginsData() (below). + */ +function requestPluginsData() { + chrome.send('requestPluginsData', []); +} + +/** + * Called by the dom_ui_ to re-populate the page with data representing the + * current state of installed plugins. + */ +function returnPluginsData(pluginsData){ + var bodyContainer = document.getElementById('body-container'); + var body = document.body; + + // Set all page content to be visible so we can measure heights. + bodyContainer.style.visibility = 'hidden'; + body.className = ''; + var slidables = document.getElementsByClassName('showInTmiMode'); + for (var i = 0; i < slidables.length; i++) + slidables[i].style.height = 'auto'; + + renderTemplate(pluginsData); + + // Make sure the left column (with "Description:", "Location:", etc.) is the + // same size for all plugins. + var labels = document.getElementsByClassName('plugin-details-label'); + var maxLabelWidth = 0; + for (var i = 0; i < labels.length; i++) + labels[i].style.width = 'auto'; + for (var i = 0; i < labels.length; i++) + maxLabelWidth = Math.max(maxLabelWidth, labels[i].offsetWidth); + for (var i = 0; i < labels.length; i++) + labels[i].style.width = maxLabelWidth + 'px'; + + // Explicitly set the height for each element that wants to be "slid" in and + // out when the tmiModeExpanded is toggled. + var slidables = document.getElementsByClassName('showInTmiMode'); + for (var i = 0; i < slidables.length; i++) + slidables[i].style.height = slidables[i].offsetHeight + 'px'; + + // Reset visibility of page based on the current tmi mode. + document.getElementById('collapse').style.display = + tmiModeExpanded ? 'inline' : 'none'; + document.getElementById('expand').style.display = + tmiModeExpanded ? 'none' : 'inline'; + bodyContainer.style.visibility = 'visible'; + body.className = tmiModeExpanded ? + 'showTmiModeInitial' : 'hideTmiModeInitial'; +} + +/** + * Handles a 'enable' or 'disable' button getting clicked. + */ +function handleEnablePlugin(node, enable) { + // Tell the C++ PluginsDOMHandler to enable/disable the plugin. + chrome.send('enablePlugin', [node.pluginPath, String(enable)]); + requestPluginsData(); +} + +// Keeps track of whether details have been made visible (expanded) or not. +var tmiModeExpanded = false; + +/* + * Toggles visibility of details. + */ +function toggleTmiMode() { + tmiModeExpanded = !tmiModeExpanded; + + document.getElementById('collapse').style.display = + tmiModeExpanded ? 'inline' : 'none'; + document.getElementById('expand').style.display = + tmiModeExpanded ? 'none' : 'inline'; + + document.body.className = + tmiModeExpanded ? 'showTmiMode' : 'hideTmiMode'; +} + +/** + * Determines whether a plugin's version should be displayed. + */ +function shouldDisplayPluginVersion(plugin) { + return !!plugin.version; +} + +/** + * Determines whether a plugin's description should be displayed. + */ +function shouldDisplayPluginDescription(plugin) { + // Only display the description if it's not blank and if it's not just the + // name, version, or combination thereof. + return plugin.description && + plugin.description != plugin.name && + plugin.description != plugin.version && + plugin.description != 'Version ' + plugin.version && + plugin.description != plugin.name + ' ' + plugin.version; +} + +/** + * Formats a file extension for display. + */ +function formatFileExtension(ext) { + return '.' + ext; +} + +// Unfortunately, we don't have notifications for plugin (list) status changes +// (yet), so in the meanwhile just update regularly. +setInterval('requestPluginsData()', 30000); + +// Get data and have it displayed upon loading. +window.onload = requestPluginsData; + +</script> +</head> +<body i18n-values=".style.fontFamily:fontfamily;.style.fontSize:fontsize"> +<div id="body-container" style="visibility:hidden"> + + <div id="header"><h1 i18n-content="pluginsTitle">TITLE</h1></div> + + <div id="pluginTemplate"> + + <div id="container" class="vbox-container"> + <div id="top" class="wbox"> + + <div class="section-header"> + <table cellpadding="0" cellspacing="0"><tr valign="center"> + <td> + <span class="section-header-title" i18n-content="pluginsTitle" + >TITLE</span> + <span class="section-header-title" + jsdisplay="plugins.length > 0">(<span + jscontent="plugins.length"></span>)</span> + </td> + <td width="18"> + <img id="collapse" class="tmi-mode-image" + style="display:none" onclick="toggleTmiMode();" + src="minus.png"></img> + <img id="expand" class="tmi-mode-image" + onclick="toggleTmiMode();" src="plus.png"></img> + </td> + <td> + <div class="tmi-mode-link"> + <a onclick="toggleTmiMode();" style="cursor: default" + i18n-content="pluginsDetailsModeLink">DETAILS</a> + </div> + </td> + </tr></table> + </div> + + </div> + </div> + + <div class="content"> + <div class="plugin-name no-plugins" jsdisplay="plugins.length === 0"> + <div i18n-content="noPlugins">NO_PLUGINS_ARE_INSTALLED</div> + </div> + + <div jsdisplay="plugins.length > 0"> + <div class="plugin" jsselect="plugins"> + <table width="100%" cellpadding="2" cellspacing="0"> + <tr jsvalues= + ".className:enabled ? 'plugin_enabled' : 'plugin_disabled'"> + <td valign="top"> + <div class="plugin-text"> + <div> + <span class="plugin-name" + jscontent="name">PLUGIN NAME</span> + <span jsdisplay="shouldDisplayPluginVersion($this)"> + - <span i18n-content="pluginVersion">VERSION</span> + <span jscontent="version">x.x.x.x</span> + </span> + <span jsdisplay="!enabled" + i18n-content="pluginDisabled">(DISABLED)</span> + </div> + <div class="plugin-details"> + <div><table><tr jsdisplay="shouldDisplayPluginDescription($this)"> + <td class="plugin-details-label" + i18n-content="pluginDescription">DESCRIPTION:</td> + <td jsvalues=".innerHTML:description"></td> + </tr></table></div> + <div><table><tr> + <td class="plugin-details-label" + i18n-content="pluginPath">PATH:</td> + <td jscontent="path"></td> + </tr></table></div> + <div class="showInTmiMode"> + <table><tr jsdisplay="mimeTypes.length > 0"> + <td class="plugin-details-label" + i18n-content="pluginMimeTypes">MIME_TYPES:</td> + <td><table width="100%" class="mime_types"> + <tr class="header"> + <td i18n-content="pluginMimeTypesMimeType" + >MIME type</td> + <td i18n-content="pluginMimeTypesDescription" + >DESCRIPTION</td> + <td i18n-content="pluginMimeTypesFileExtensions" + >FILE_EXTENSIONS</td> + </tr> + <tr jsselect="mimeTypes"> + <td jscontent="mimeType"></td> + <td jscontent="description"></td> + <td><table jsdisplay="fileExtensions.length > 0" + class="hlisting"> + <tr><td jsselect="fileExtensions"> + <span jscontent="formatFileExtension($this)"></span> + </td></tr> + </table></td> + </tr> + </table></td> + </tr></table> + </div> + </div> + </div> + + <div class="plugin-actions"> + <span> + <a + jsvalues=".pluginPath:path" + jsdisplay="enabled" + onclick="handleEnablePlugin(this, false)" + href="javascript:void();" + i18n-content="disable" + >DISABLE</a> + <a + jsvalues=".pluginPath:path" + jsdisplay="!enabled" + onclick="handleEnablePlugin(this, true)" + href="javascript:void();" + i18n-content="enable" + >ENABLE</a> + </span> + </div> + </td> + </tr> + </table> + </div> + </div> + </div> + </div> +</div> +</body> +</html> diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 935162d..b408402 100755 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -866,6 +866,8 @@ 'browser/dom_ui/new_tab_ui.h', 'browser/dom_ui/ntp_resource_cache.cc', 'browser/dom_ui/ntp_resource_cache.h', + 'browser/dom_ui/plugins_ui.cc', + 'browser/dom_ui/plugins_ui.h', 'browser/dom_ui/print_ui.cc', 'browser/dom_ui/print_ui.h', 'browser/dom_ui/shown_sections_handler.cc', diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index 62486e3..5e4f84d 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc @@ -163,38 +163,36 @@ const wchar_t kDnsStartupPrefetchList[] = L"StartupDNSPrefetchList"; // sub-resource hostnames (and expected latency benefits from pre-resolving such // sub-resource hostnames). // This list is adaptively grown and pruned. -extern const wchar_t kDnsHostReferralList[] = L"HostReferralList"; +const wchar_t kDnsHostReferralList[] = L"HostReferralList"; // Is the cookie prompt expanded? -extern const wchar_t kCookiePromptExpanded[] = L"cookieprompt.expanded"; +const wchar_t kCookiePromptExpanded[] = L"cookieprompt.expanded"; #if defined(USE_NSS) // Prefs for SSLConfigServicePref. Currently, these are only present on // and used by NSS-using OSes. -extern const wchar_t kCertRevocationCheckingEnabled[] = - L"ssl.rev_checking.enabled"; -extern const wchar_t kSSL2Enabled[] = L"ssl.ssl2.enabled"; -extern const wchar_t kSSL3Enabled[] = L"ssl.ssl3.enabled"; -extern const wchar_t kTLS1Enabled[] = L"ssl.tls1.enabled"; +const wchar_t kCertRevocationCheckingEnabled[] = L"ssl.rev_checking.enabled"; +const wchar_t kSSL2Enabled[] = L"ssl.ssl2.enabled"; +const wchar_t kSSL3Enabled[] = L"ssl.ssl3.enabled"; +const wchar_t kTLS1Enabled[] = L"ssl.tls1.enabled"; #endif #if defined(OS_CHROMEOS) // A string pref set to the timezone. -extern const wchar_t kTimeZone[] = L"settings.datetime.timezone"; +const wchar_t kTimeZone[] = L"settings.datetime.timezone"; // A boolean pref set to true if TapToClick is being done in browser. -extern const wchar_t kTapToClickEnabled[] = - L"settings.touchpad.enable_tap_to_click"; +const wchar_t kTapToClickEnabled[] = L"settings.touchpad.enable_tap_to_click"; // A boolean pref set to true if VertEdgeScroll is being done in browser. -extern const wchar_t kVertEdgeScrollEnabled[] = +const wchar_t kVertEdgeScrollEnabled[] = L"settings.touchpad.enable_vert_edge_scroll"; // A integer pref for the touchpad speed factor. -extern const wchar_t kTouchpadSpeedFactor[] = L"settings.touchpad.speed_factor"; +const wchar_t kTouchpadSpeedFactor[] = L"settings.touchpad.speed_factor"; // A integer pref for the touchpad sensitivity. -extern const wchar_t kTouchpadSensitivity[] = L"settings.touchpad.sensitivity"; +const wchar_t kTouchpadSensitivity[] = L"settings.touchpad.sensitivity"; #endif // The disabled messages in IPC logging. @@ -273,6 +271,9 @@ const wchar_t kExtensionsUIDeveloperMode[] = L"extensions.ui.developer_mode"; // actions toolbar. const wchar_t kExtensionToolbarSize[] = L"extensions.toolbarsize"; +// List pref containing information (dictionaries) on plugins. +const wchar_t kPluginsPluginsList[] = L"plugins.plugins_list"; + // Boolean that indicates whether we should check if we are the default browser // on start-up. const wchar_t kCheckDefaultBrowser[] = L"browser.check_default_browser"; @@ -407,7 +408,7 @@ const wchar_t kStabilityStatsVersion[] = // Build time, in seconds since an epoch, which is used to assure that stability // metrics reported reflect stability of the same build. -extern const wchar_t kStabilityStatsBuildTime[] = +const wchar_t kStabilityStatsBuildTime[] = L"user_experience_metrics.stability.stats_buildtime"; // False if we received a session end and either we crashed during processing diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index a8b2de9..eecb1c1 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h @@ -110,6 +110,7 @@ extern const wchar_t kCurrentThemeTints[]; extern const wchar_t kCurrentThemeDisplayProperties[]; extern const wchar_t kExtensionsUIDeveloperMode[]; extern const wchar_t kExtensionToolbarSize[]; +extern const wchar_t kPluginsPluginsList[]; extern const wchar_t kCheckDefaultBrowser[]; #if defined(OS_MACOSX) extern const wchar_t kShowUpdatePromotionInfoBar[]; diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc index 9d24745..d770685 100644 --- a/chrome/common/url_constants.cc +++ b/chrome/common/url_constants.cc @@ -38,11 +38,11 @@ const char* kSavableSchemes[] = { const char kAboutBlankURL[] = "about:blank"; const char kAboutCacheURL[] = "about:cache"; -const char kAboutNetInternalsURL[] = "about:net-internals"; const char kAboutCrashURL[] = "about:crash"; const char kAboutCreditsURL[] = "about:credits"; const char kAboutHangURL[] = "about:hang"; const char kAboutMemoryURL[] = "about:memory"; +const char kAboutNetInternalsURL[] = "about:net-internals"; const char kAboutShorthangURL[] = "about:shorthang"; const char kAboutTermsURL[] = "about:terms"; @@ -55,6 +55,7 @@ const char kChromeUIDevToolsURL[] = "chrome://devtools/"; const char kChromeUIDownloadsURL[] = "chrome://downloads/"; const char kChromeUIExtensionsURL[] = "chrome://extensions/"; const char kChromeUIHistoryURL[] = "chrome://history/"; +const char kChromeUIPluginsURL[] = "chrome://plugins/"; const char kChromeUIFileBrowseURL[] = "chrome://filebrowse/"; const char kChromeUIMediaplayerURL[] = "chrome://mediaplayer/"; const char kChromeUIIPCURL[] = "chrome://about/ipc"; @@ -68,6 +69,7 @@ const char kChromeUIDownloadsHost[] = "downloads"; const char kChromeUIExtensionsHost[] = "extensions"; const char kChromeUIFavIconPath[] = "favicon"; const char kChromeUIHistoryHost[] = "history"; +const char kChromeUIPluginsHost[] = "plugins"; const char kChromeUIFileBrowseHost[] = "filebrowse"; const char kChromeUIMediaplayerHost[] = "mediaplayer"; const char kChromeUIInspectorHost[] = "inspector"; diff --git a/chrome/common/url_constants.h b/chrome/common/url_constants.h index 665bd66..d4f2ee5 100644 --- a/chrome/common/url_constants.h +++ b/chrome/common/url_constants.h @@ -32,7 +32,7 @@ extern const char kStandardSchemeSeparator[]; // Null terminated list of schemes that are savable. extern const char* kSavableSchemes[]; -// About URLs (including schmes). +// About URLs (including schemes). extern const char kAboutBlankURL[]; extern const char kAboutBrowserCrash[]; extern const char kAboutCacheURL[]; @@ -51,6 +51,7 @@ extern const char kChromeUIDevToolsURL[]; extern const char kChromeUIDownloadsURL[]; extern const char kChromeUIExtensionsURL[]; extern const char kChromeUIHistoryURL[]; +extern const char kChromeUIPluginsURL[]; extern const char kChromeUIFileBrowseURL[]; extern const char kChromeUIMediaplayerURL[]; extern const char kChromeUIIPCURL[]; @@ -66,6 +67,7 @@ extern const char kChromeUIDownloadsHost[]; extern const char kChromeUIExtensionsHost[]; extern const char kChromeUIFavIconPath[]; extern const char kChromeUIHistoryHost[]; +extern const char kChromeUIPluginsHost[]; extern const char kChromeUIFileBrowseHost[]; extern const char kChromeUIMediaplayerHost[]; extern const char kChromeUIInspectorHost[]; diff --git a/webkit/glue/plugins/plugin_lib_mac.mm b/webkit/glue/plugins/plugin_lib_mac.mm index 64d34c3..b6ced70 100644 --- a/webkit/glue/plugins/plugin_lib_mac.mm +++ b/webkit/glue/plugins/plugin_lib_mac.mm @@ -123,6 +123,7 @@ bool ReadPlistPluginInfo(const FilePath& filename, CFBundleRef bundle, info->desc = base::SysNSStringToWide(plugin_desc); else info->desc = UTF8ToWide(filename.BaseName().value()); + info->enabled = true; return true; } @@ -220,6 +221,7 @@ bool ReadSTRPluginInfo(const FilePath& filename, CFBundleRef bundle, info->desc = UTF8ToWide(plugin_descs[0]); else info->desc = UTF8ToWide(filename.BaseName().value()); + info->enabled = true; return true; } diff --git a/webkit/glue/plugins/plugin_lib_posix.cc b/webkit/glue/plugins/plugin_lib_posix.cc index e738b67..6541a66 100644 --- a/webkit/glue/plugins/plugin_lib_posix.cc +++ b/webkit/glue/plugins/plugin_lib_posix.cc @@ -131,6 +131,7 @@ bool PluginLib::ReadWebPluginInfo(const FilePath& filename, return false; info->path = filename; + info->enabled = true; // Attempt to swap in the wrapped plugin if this is nspluginwrapper. UnwrapNSPluginWrapper(&dl, &info->path); diff --git a/webkit/glue/plugins/plugin_list.cc b/webkit/glue/plugins/plugin_list.cc index e8565d8..d0199d4 100644 --- a/webkit/glue/plugins/plugin_list.cc +++ b/webkit/glue/plugins/plugin_list.cc @@ -1,9 +1,11 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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 "webkit/glue/plugins/plugin_list.h" +#include <algorithm> + #include "base/lazy_instance.h" #include "base/logging.h" #include "base/string_util.h" @@ -106,6 +108,7 @@ bool PluginList::CreateWebPluginInfo(const PluginVersionInfo& pvi, info->desc = pvi.file_description; info->version = pvi.file_version; info->path = pvi.path; + info->enabled = true; for (size_t i = 0; i < mime_types.size(); ++i) { WebPluginMimeType mime_type; @@ -214,7 +217,17 @@ void PluginList::LoadPlugins(bool refresh) { base::TimeDelta elapsed = end_time - start_time; DLOG(INFO) << "Loaded plugin list in " << elapsed.InMilliseconds() << " ms."; + // Only update the data now since loading plugins can take a while. AutoLock lock(lock_); + + // Go through and mark new plugins in the disabled list as, well, disabled. + for (std::vector<WebPluginInfo>::iterator it = new_plugins.begin(); + it != new_plugins.end(); + ++it) { + if (disabled_plugins_.find(it->path) != disabled_plugins_.end()) + it->enabled = false; + } + plugins_ = new_plugins; plugins_loaded_ = true; } @@ -331,6 +344,20 @@ void PluginList::GetPlugins(bool refresh, std::vector<WebPluginInfo>* plugins) { *plugins = plugins_; } +void PluginList::GetEnabledPlugins(bool refresh, + std::vector<WebPluginInfo>* plugins) { + LoadPlugins(refresh); + + plugins->clear(); + AutoLock lock(lock_); + for (std::vector<WebPluginInfo>::const_iterator it = plugins_.begin(); + it != plugins_.end(); + ++it) { + if (it->enabled) + plugins->push_back(*it); + } +} + bool PluginList::GetPluginInfo(const GURL& url, const std::string& mime_type, bool allow_wildcard, @@ -362,6 +389,55 @@ bool PluginList::GetPluginInfoByPath(const FilePath& plugin_path, return false; } +bool PluginList::EnablePlugin(const FilePath& filename) { + AutoLock lock(lock_); + + bool did_enable = false; + + std::set<FilePath>::iterator entry = disabled_plugins_.find(filename); + if (entry == disabled_plugins_.end()) + return did_enable; // Early exit if plugin not in disabled list. + + disabled_plugins_.erase(entry); // Remove from disabled list. + + // Set enabled flags if necessary. + for (std::vector<WebPluginInfo>::iterator it = plugins_.begin(); + it != plugins_.end(); + ++it) { + if (it->path == filename) { + DCHECK(!it->enabled); // Should have been disabled. + it->enabled = true; + did_enable = true; + } + } + + return did_enable; +} + +bool PluginList::DisablePlugin(const FilePath& filename) { + AutoLock lock(lock_); + + bool did_disable = false; + + if (disabled_plugins_.find(filename) != disabled_plugins_.end()) + return did_disable; // Early exit if plugin already in disabled list. + + disabled_plugins_.insert(filename); // Add to disabled list. + + // Unset enabled flags if necessary. + for (std::vector<WebPluginInfo>::iterator it = plugins_.begin(); + it != plugins_.end(); + ++it) { + if (it->path == filename) { + DCHECK(it->enabled); // Should have been enabled. + it->enabled = false; + did_disable = true; + } + } + + return did_disable; +} + void PluginList::Shutdown() { // TODO } diff --git a/webkit/glue/plugins/plugin_list.h b/webkit/glue/plugins/plugin_list.h index 0017399..91bf23f 100644 --- a/webkit/glue/plugins/plugin_list.h +++ b/webkit/glue/plugins/plugin_list.h @@ -5,6 +5,7 @@ #ifndef WEBKIT_GLUE_PLUGINS_PLUGIN_LIST_H_ #define WEBKIT_GLUE_PLUGINS_PLUGIN_LIST_H_ +#include <set> #include <string> #include <vector> #include <set> @@ -114,9 +115,12 @@ class PluginList { // Shutdown all plugins. Should be called at process teardown. void Shutdown(); - // Get all the plugins + // Get all the plugins. void GetPlugins(bool refresh, std::vector<WebPluginInfo>* plugins); + // Get all the enabled plugins. + void GetEnabledPlugins(bool refresh, std::vector<WebPluginInfo>* plugins); + // Returns true if a plugin is found for the given url and mime type. // The mime type which corresponds to the URL is optionally returned // back. @@ -137,6 +141,19 @@ class PluginList { void LoadPlugin(const FilePath& filename, std::vector<WebPluginInfo>* plugins); + // Enable a specific plugin, specified by path. Returns |true| iff a plugin + // currently in the plugin list was actually enabled as a result; regardless + // of return value, if a plugin is found in the future with the given name, it + // will be enabled. Note that plugins are enabled by default as far as + // |PluginList| is concerned. + bool EnablePlugin(const FilePath& filename); + + // Disable a specific plugin, specified by path. Returns |true| iff a plugin + // currently in the plugin list was actually disabled as a result; regardless + // of return value, if a plugin is found in the future with the given name, it + // will be disabled. + bool DisablePlugin(const FilePath& filename); + private: // Constructors are private for singletons PluginList(); @@ -222,6 +239,9 @@ class PluginList { // Holds information about internal plugins. std::vector<PluginVersionInfo> internal_plugins_; + // Path names of plugins to disable (the default is to enable them all). + std::set<FilePath> disabled_plugins_; + // Need synchronization for the above members since this object can be // accessed on multiple threads. Lock lock_; diff --git a/webkit/glue/webplugininfo.h b/webkit/glue/webplugininfo.h index 77c59ea..21f34df 100644 --- a/webkit/glue/webplugininfo.h +++ b/webkit/glue/webplugininfo.h @@ -39,6 +39,9 @@ struct WebPluginInfo { // A list of all the mime types that this plugin supports. std::vector<WebPluginMimeType> mime_types; + + // Whether the plugin is enabled. + bool enabled; }; #endif // WEBKIT_GLUE_WEBPLUGININFO_H_ |