diff options
author | bauerb@chromium.org <bauerb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-02-03 10:26:50 +0000 |
---|---|---|
committer | bauerb@chromium.org <bauerb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-02-03 10:26:50 +0000 |
commit | e242401ae4974a8947677136751a547ec8449adf (patch) | |
tree | c1c97e54f3feea11f266d56a7c1a43df4160af82 | |
parent | acca50df1d355cfc303c906e940d87d75a714d38 (diff) | |
download | chromium_src-e242401ae4974a8947677136751a547ec8449adf.zip chromium_src-e242401ae4974a8947677136751a547ec8449adf.tar.gz chromium_src-e242401ae4974a8947677136751a547ec8449adf.tar.bz2 |
Merge different plug-in placeholders into one class.
This allows us to combine functionality from different plug-in placeholders, i.e. installing *and* loading a plug-in.
Also refactor ChromeContentRendererClient::CreatePlugin to be (hopefully) simpler: It's just a big switch statement now that configures the plug-in placeholder.
BUG=92796
TEST=none
Review URL: http://codereview.chromium.org/9309037
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@120310 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/plugin_observer.cc | 44 | ||||
-rw-r--r-- | chrome/browser/plugin_observer.h | 9 | ||||
-rw-r--r-- | chrome/chrome_renderer.gypi | 4 | ||||
-rw-r--r-- | chrome/common/render_messages.h | 9 | ||||
-rw-r--r-- | chrome/renderer/chrome_content_renderer_client.cc | 264 | ||||
-rw-r--r-- | chrome/renderer/plugins/blocked_plugin.cc | 232 | ||||
-rw-r--r-- | chrome/renderer/plugins/blocked_plugin.h | 83 | ||||
-rw-r--r-- | chrome/renderer/plugins/missing_plugin.cc | 249 | ||||
-rw-r--r-- | chrome/renderer/plugins/missing_plugin.h | 79 | ||||
-rw-r--r-- | chrome/renderer/plugins/plugin_placeholder.cc | 356 | ||||
-rw-r--r-- | chrome/renderer/plugins/plugin_placeholder.h | 134 |
11 files changed, 648 insertions, 815 deletions
diff --git a/chrome/browser/plugin_observer.cc b/chrome/browser/plugin_observer.cc index 5ec70897..39afcd5 100644 --- a/chrome/browser/plugin_observer.cc +++ b/chrome/browser/plugin_observer.cc @@ -364,11 +364,11 @@ void ConfirmInstallDialogDelegate::OnlyWeakObserversLeft() { // PluginObserver ------------------------------------------------------------- #if defined(ENABLE_PLUGIN_INSTALLATION) -class PluginObserver::MissingPluginHost : public PluginInstallerObserver { +class PluginObserver::PluginPlaceholderHost : public PluginInstallerObserver { public: - MissingPluginHost(PluginObserver* observer, - int routing_id, - PluginInstaller* installer) + PluginPlaceholderHost(PluginObserver* observer, + int routing_id, + PluginInstaller* installer) : PluginInstallerObserver(installer), observer_(observer), routing_id_(routing_id) { @@ -414,7 +414,7 @@ PluginObserver::PluginObserver(TabContentsWrapper* tab_contents) PluginObserver::~PluginObserver() { #if defined(ENABLE_PLUGIN_INSTALLATION) - STLDeleteValues(&missing_plugins_); + STLDeleteValues(&plugin_placeholders_); #endif } @@ -422,11 +422,13 @@ bool PluginObserver::OnMessageReceived(const IPC::Message& message) { IPC_BEGIN_MESSAGE_MAP(PluginObserver, message) IPC_MESSAGE_HANDLER(ChromeViewHostMsg_BlockedOutdatedPlugin, OnBlockedOutdatedPlugin) + IPC_MESSAGE_HANDLER(ChromeViewHostMsg_BlockedUnauthorizedPlugin, + OnBlockedUnauthorizedPlugin) #if defined(ENABLE_PLUGIN_INSTALLATION) IPC_MESSAGE_HANDLER(ChromeViewHostMsg_FindMissingPlugin, OnFindMissingPlugin) - IPC_MESSAGE_HANDLER(ChromeViewHostMsg_RemoveMissingPluginHost, - OnRemoveMissingPluginHost) + IPC_MESSAGE_HANDLER(ChromeViewHostMsg_RemovePluginPlaceholderHost, + OnRemovePluginPlaceholderHost) #endif IPC_MESSAGE_HANDLER(ChromeViewHostMsg_OpenAboutPlugins, OnOpenAboutPlugins) @@ -440,14 +442,18 @@ bool PluginObserver::OnMessageReceived(const IPC::Message& message) { void PluginObserver::OnBlockedOutdatedPlugin(const string16& name, const GURL& update_url) { InfoBarTabHelper* infobar_helper = tab_contents_->infobar_tab_helper(); - infobar_helper->AddInfoBar(update_url.is_empty() ? - static_cast<InfoBarDelegate*>(new BlockedPluginInfoBarDelegate( - infobar_helper, - tab_contents_->profile()->GetHostContentSettingsMap(), - name)) : + infobar_helper->AddInfoBar( new OutdatedPluginInfoBarDelegate(infobar_helper, name, update_url)); } +void PluginObserver::OnBlockedUnauthorizedPlugin(const string16& name) { + InfoBarTabHelper* infobar_helper = tab_contents_->infobar_tab_helper(); + infobar_helper->AddInfoBar(new BlockedPluginInfoBarDelegate( + infobar_helper, + tab_contents_->profile()->GetHostContentSettingsMap(), + name)); +} + #if defined(ENABLE_PLUGIN_INSTALLATION) void PluginObserver::OnFindMissingPlugin(int placeholder_id, const std::string& mime_type) { @@ -464,8 +470,8 @@ void PluginObserver::OnFindMissingPlugin(int placeholder_id, void PluginObserver::FoundMissingPlugin(int placeholder_id, const std::string& mime_type, PluginInstaller* installer) { - missing_plugins_[placeholder_id] = - new MissingPluginHost(this, placeholder_id, installer); + plugin_placeholders_[placeholder_id] = + new PluginPlaceholderHost(this, placeholder_id, installer); InfoBarTabHelper* infobar_helper = tab_contents_->infobar_tab_helper(); InfoBarDelegate* delegate = PluginInstallerInfoBarDelegate::Create( infobar_helper, installer, @@ -493,15 +499,15 @@ void PluginObserver::InstallMissingPlugin(PluginInstaller* installer) { } } -void PluginObserver::OnRemoveMissingPluginHost(int placeholder_id) { - std::map<int, MissingPluginHost*>::iterator it = - missing_plugins_.find(placeholder_id); - if (it == missing_plugins_.end()) { +void PluginObserver::OnRemovePluginPlaceholderHost(int placeholder_id) { + std::map<int, PluginPlaceholderHost*>::iterator it = + plugin_placeholders_.find(placeholder_id); + if (it == plugin_placeholders_.end()) { NOTREACHED(); return; } delete it->second; - missing_plugins_.erase(it); + plugin_placeholders_.erase(it); } #endif // defined(ENABLE_PLUGIN_INSTALLATION) diff --git a/chrome/browser/plugin_observer.h b/chrome/browser/plugin_observer.h index 58f3e11..4000fce 100644 --- a/chrome/browser/plugin_observer.h +++ b/chrome/browser/plugin_observer.h @@ -32,10 +32,11 @@ class PluginObserver : public content::WebContentsObserver { private: #if defined(ENABLE_PLUGIN_INSTALLATION) - class MissingPluginHost; + class PluginPlaceholderHost; #endif void OnBlockedOutdatedPlugin(const string16& name, const GURL& update_url); + void OnBlockedUnauthorizedPlugin(const string16& name); #if defined(ENABLE_PLUGIN_INSTALLATION) void OnFindMissingPlugin(int placeholder_id, const std::string& mime_type); @@ -46,15 +47,15 @@ class PluginObserver : public content::WebContentsObserver { void InstallMissingPlugin(PluginInstaller* installer); #endif void OnOpenAboutPlugins(); - void OnRemoveMissingPluginHost(int placeholder_id); + void OnRemovePluginPlaceholderHost(int placeholder_id); base::WeakPtrFactory<PluginObserver> weak_ptr_factory_; TabContentsWrapper* tab_contents_; #if defined(ENABLE_PLUGIN_INSTALLATION) - // Stores all MissingPluginHosts, keyed by their routing ID.ß - std::map<int, MissingPluginHost*> missing_plugins_; + // Stores all PluginPlaceholderHosts, keyed by their routing ID. + std::map<int, PluginPlaceholderHost*> plugin_placeholders_; #endif DISALLOW_COPY_AND_ASSIGN(PluginObserver); diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi index 18c3fd1..030233e 100644 --- a/chrome/chrome_renderer.gypi +++ b/chrome/chrome_renderer.gypi @@ -172,10 +172,6 @@ 'renderer/page_click_tracker.h', 'renderer/page_load_histograms.cc', 'renderer/page_load_histograms.h', - 'renderer/plugins/blocked_plugin.cc', - 'renderer/plugins/blocked_plugin.h', - 'renderer/plugins/missing_plugin.cc', - 'renderer/plugins/missing_plugin.h', 'renderer/plugins/plugin_placeholder.cc', 'renderer/plugins/plugin_placeholder.h', 'renderer/plugins/plugin_uma.cc', diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h index 9ab4a06..4792706 100644 --- a/chrome/common/render_messages.h +++ b/chrome/common/render_messages.h @@ -434,8 +434,8 @@ IPC_MESSAGE_ROUTED2(ChromeViewHostMsg_FindMissingPlugin, std::string /* mime_type */) // Notifies the browser that a missing plug-in placeholder has been removed, so -// the corresponding MissingPluginHost can be deleted. -IPC_MESSAGE_ROUTED1(ChromeViewHostMsg_RemoveMissingPluginHost, +// the corresponding PluginPlaceholderHost can be deleted. +IPC_MESSAGE_ROUTED1(ChromeViewHostMsg_RemovePluginPlaceholderHost, int /* placeholder_id */) // Notifies a missing plug-in placeholder that a plug-in with name |plugin_name| @@ -546,6 +546,11 @@ IPC_MESSAGE_ROUTED2(ChromeViewHostMsg_BlockedOutdatedPlugin, string16, /* name */ GURL /* update_url */) +// Notifies when a plugin couldn't be loaded because it requires +// user authorization. +IPC_MESSAGE_ROUTED1(ChromeViewHostMsg_BlockedUnauthorizedPlugin, + string16 /* name */) + // Provide the browser process with information about the WebCore resource // cache and current renderer framerate. IPC_MESSAGE_CONTROL1(ChromeViewHostMsg_ResourceTypeStats, diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index 09ab635..e260d4e 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc @@ -47,8 +47,7 @@ #include "chrome/renderer/net/renderer_net_predictor.h" #include "chrome/renderer/page_click_tracker.h" #include "chrome/renderer/page_load_histograms.h" -#include "chrome/renderer/plugins/blocked_plugin.h" -#include "chrome/renderer/plugins/missing_plugin.h" +#include "chrome/renderer/plugins/plugin_placeholder.h" #include "chrome/renderer/plugins/plugin_uma.h" #include "chrome/renderer/prerender/prerender_helper.h" #include "chrome/renderer/prerender/prerender_webmediaplayer.h" @@ -329,135 +328,162 @@ WebPlugin* ChromeContentRendererClient::CreatePlugin( const ChromeViewHostMsg_GetPluginInfo_Status& status, const webkit::WebPluginInfo& plugin, const std::string& actual_mime_type) { - CommandLine* cmd = CommandLine::ForCurrentProcess(); + ChromeViewHostMsg_GetPluginInfo_Status::Value status_value = status.value; GURL url(original_params.url); std::string orig_mime_type = original_params.mimeType.utf8(); - if (status.value == ChromeViewHostMsg_GetPluginInfo_Status::kNotFound) { + PluginPlaceholder* placeholder = NULL; + if (status_value == ChromeViewHostMsg_GetPluginInfo_Status::kNotFound) { MissingPluginReporter::GetInstance()->ReportPluginMissing( orig_mime_type, url); - return MissingPlugin::Create(render_view, frame, original_params); - } - - scoped_ptr<webkit::npapi::PluginGroup> group( - webkit::npapi::PluginList::Singleton()->GetPluginGroup(plugin)); - - if (status.value == ChromeViewHostMsg_GetPluginInfo_Status::kDisabled) { - return BlockedPlugin::Create( - render_view, frame, original_params, plugin, group.get(), - IDR_DISABLED_PLUGIN_HTML, IDS_PLUGIN_DISABLED, false, false); - } + placeholder = PluginPlaceholder::CreateMissingPlugin( + render_view, frame, original_params); + } else { + scoped_ptr<webkit::npapi::PluginGroup> group( + webkit::npapi::PluginList::Singleton()->GetPluginGroup(plugin)); + string16 name = group->GetGroupName(); - WebPluginParams params(original_params); - for (size_t i = 0; i < plugin.mime_types.size(); ++i) { - if (plugin.mime_types[i].mime_type == actual_mime_type) { - AppendParams(plugin.mime_types[i].additional_param_names, - plugin.mime_types[i].additional_param_values, - ¶ms.attributeNames, - ¶ms.attributeValues); - break; + // TODO(bauerb): This should be in content/. + WebPluginParams params(original_params); + for (size_t i = 0; i < plugin.mime_types.size(); ++i) { + if (plugin.mime_types[i].mime_type == actual_mime_type) { + AppendParams(plugin.mime_types[i].additional_param_names, + plugin.mime_types[i].additional_param_values, + ¶ms.attributeNames, + ¶ms.attributeValues); + break; + } } - } - - if (params.mimeType.isNull() && (actual_mime_type.size() > 0)) { - // Webkit might say that mime type is null while we already know the - // actual mime type via ChromeViewHostMsg_GetPluginInfo. In that case - // we should use what we know since WebpluginDelegateProxy does some - // specific initializations based on this information. - params.mimeType = WebString::fromUTF8(actual_mime_type.c_str()); - } - - if (status.value == - ChromeViewHostMsg_GetPluginInfo_Status::kOutdatedBlocked) { - render_view->Send(new ChromeViewHostMsg_BlockedOutdatedPlugin( - render_view->GetRoutingId(), group->GetGroupName(), - GURL(group->GetUpdateURL()))); - } - if (status.value == - ChromeViewHostMsg_GetPluginInfo_Status::kOutdatedBlocked || - status.value == - ChromeViewHostMsg_GetPluginInfo_Status::kOutdatedDisallowed) { - return BlockedPlugin::Create( - render_view, frame, params, plugin, group.get(), - IDR_BLOCKED_PLUGIN_HTML, IDS_PLUGIN_OUTDATED, false, - status.value == - ChromeViewHostMsg_GetPluginInfo_Status::kOutdatedBlocked); - } - - ContentSettingsObserver* observer = ContentSettingsObserver::Get(render_view); - - if (status.value == - ChromeViewHostMsg_GetPluginInfo_Status::kUnauthorized && - !observer->plugins_temporarily_allowed()) { - render_view->Send(new ChromeViewHostMsg_BlockedOutdatedPlugin( - render_view->GetRoutingId(), group->GetGroupName(), GURL())); - return BlockedPlugin::Create( - render_view, frame, params, plugin, group.get(), - IDR_BLOCKED_PLUGIN_HTML, IDS_PLUGIN_NOT_AUTHORIZED, false, true); - } - - bool is_nacl_plugin = (plugin.name == ASCIIToUTF16( - chrome::ChromeContentClient::kNaClPluginName)); - if (status.value == ChromeViewHostMsg_GetPluginInfo_Status::kAllowed || - observer->plugins_temporarily_allowed()) { - // Delay loading plugins if prerendering. - if (prerender::PrerenderHelper::IsPrerendering(render_view)) { - return BlockedPlugin::Create( - render_view, frame, params, plugin, group.get(), - IDR_CLICK_TO_PLAY_PLUGIN_HTML, IDS_PLUGIN_LOAD, true, true); + if (params.mimeType.isNull() && (actual_mime_type.size() > 0)) { + // Webkit might say that mime type is null while we already know the + // actual mime type via ChromeViewHostMsg_GetPluginInfo. In that case + // we should use what we know since WebpluginDelegateProxy does some + // specific initializations based on this information. + params.mimeType = WebString::fromUTF8(actual_mime_type.c_str()); } - // Determine if NaCl is allowed for both the internal plugin and - // any external plugin that handles our MIME type. This is so NaCl - // tests will still pass. - const char* kNaClMimeType = "application/x-nacl"; - bool is_nacl_mime_type = actual_mime_type == kNaClMimeType; - bool is_nacl_enabled; - if (is_nacl_plugin) { - is_nacl_enabled = cmd->HasSwitch(switches::kEnableNaCl); - } else { - // If this is an external plugin that handles NaCl mime type, - // we want to allow Native Client, because it's how - // NaCl tests for the plugin work. - is_nacl_enabled = true; - } - if (is_nacl_plugin || is_nacl_mime_type) { - if (!IsNaClAllowed(plugin, - url, - actual_mime_type, - is_nacl_mime_type, - is_nacl_enabled, - params)) { - frame->addMessageToConsole( - WebConsoleMessage( - WebConsoleMessage::LevelError, - "Only unpacked extensions and apps installed from the Chrome" - " Web Store can load NaCl modules without enabling Native" - " Client in about:flags.")); - return BlockedPlugin::Create( - render_view, frame, params, plugin, group.get(), - IDR_BLOCKED_PLUGIN_HTML, IDS_PLUGIN_BLOCKED, false, false); - } + ContentSettingsObserver* observer = + ContentSettingsObserver::Get(render_view); + + bool is_nacl_plugin = + plugin.name == + ASCIIToUTF16(chrome::ChromeContentClient::kNaClPluginName); + ContentSettingsType content_type = + is_nacl_plugin ? CONTENT_SETTINGS_TYPE_JAVASCRIPT : + CONTENT_SETTINGS_TYPE_PLUGINS; + + if ((status_value == + ChromeViewHostMsg_GetPluginInfo_Status::kUnauthorized || + status_value == ChromeViewHostMsg_GetPluginInfo_Status::kClickToPlay || + status_value == ChromeViewHostMsg_GetPluginInfo_Status::kBlocked) && + observer->plugins_temporarily_allowed()) { + status_value = ChromeViewHostMsg_GetPluginInfo_Status::kAllowed; } - return render_view->CreatePlugin(frame, plugin, params); - } + switch (status_value) { + case ChromeViewHostMsg_GetPluginInfo_Status::kNotFound: { + NOTREACHED(); + break; + } + case ChromeViewHostMsg_GetPluginInfo_Status::kAllowed: { + // Delay loading plugins if prerendering. + if (prerender::PrerenderHelper::IsPrerendering(render_view)) { + placeholder = PluginPlaceholder::CreateBlockedPlugin( + render_view, frame, params, plugin, name, + IDR_CLICK_TO_PLAY_PLUGIN_HTML, IDS_PLUGIN_LOAD); + placeholder->set_blocked_for_prerendering(true); + placeholder->set_allow_loading(true); + break; + } - observer->DidBlockContentType( - is_nacl_plugin ? CONTENT_SETTINGS_TYPE_JAVASCRIPT : - CONTENT_SETTINGS_TYPE_PLUGINS, - group->identifier()); - if (status.value == ChromeViewHostMsg_GetPluginInfo_Status::kClickToPlay) { - RenderThread::Get()->RecordUserMetrics("Plugin_ClickToPlay"); - return BlockedPlugin::Create( - render_view, frame, params, plugin, group.get(), - IDR_CLICK_TO_PLAY_PLUGIN_HTML, IDS_PLUGIN_LOAD, false, true); - } else { - DCHECK(status.value == ChromeViewHostMsg_GetPluginInfo_Status::kBlocked); - RenderThread::Get()->RecordUserMetrics("Plugin_Blocked"); - return BlockedPlugin::Create( - render_view, frame, params, plugin, group.get(), - IDR_BLOCKED_PLUGIN_HTML, IDS_PLUGIN_BLOCKED, false, true); + // Determine if NaCl is allowed for both the internal plugin and + // any external plugin that handles our MIME type. This is so NaCl + // tests will still pass. + const char* kNaClMimeType = "application/x-nacl"; + bool is_nacl_mime_type = actual_mime_type == kNaClMimeType; + bool is_nacl_enabled; + if (is_nacl_plugin) { + is_nacl_enabled = CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableNaCl); + } else { + // If this is an external plugin that handles NaCl mime type, + // we want to allow Native Client, because it's how + // NaCl tests for the plugin work. + is_nacl_enabled = true; + } + if (is_nacl_plugin || is_nacl_mime_type) { + if (!IsNaClAllowed(plugin, + url, + actual_mime_type, + is_nacl_mime_type, + is_nacl_enabled, + params)) { + frame->addMessageToConsole( + WebConsoleMessage( + WebConsoleMessage::LevelError, + "Only unpacked extensions and apps installed from the " + "Chrome Web Store can load NaCl modules without enabling " + "Native Client in about:flags.")); + placeholder = PluginPlaceholder::CreateBlockedPlugin( + render_view, frame, params, plugin, name, + IDR_BLOCKED_PLUGIN_HTML, IDS_PLUGIN_BLOCKED); + break; + } + } + return render_view->CreatePlugin(frame, plugin, params); + } + case ChromeViewHostMsg_GetPluginInfo_Status::kDisabled: { + placeholder = PluginPlaceholder::CreateBlockedPlugin( + render_view, frame, params, plugin, name, + IDR_DISABLED_PLUGIN_HTML, IDS_PLUGIN_DISABLED); + break; + } + case ChromeViewHostMsg_GetPluginInfo_Status::kOutdatedBlocked: { + placeholder = PluginPlaceholder::CreateBlockedPlugin( + render_view, frame, params, plugin, name, + IDR_BLOCKED_PLUGIN_HTML, IDS_PLUGIN_OUTDATED); + placeholder->set_allow_loading(true); + render_view->Send(new ChromeViewHostMsg_BlockedOutdatedPlugin( + render_view->GetRoutingId(), group->GetGroupName(), + GURL(group->GetUpdateURL()))); + break; + } + case ChromeViewHostMsg_GetPluginInfo_Status::kOutdatedDisallowed: { + placeholder = PluginPlaceholder::CreateBlockedPlugin( + render_view, frame, params, plugin, name, + IDR_BLOCKED_PLUGIN_HTML, IDS_PLUGIN_OUTDATED); + break; + } + case ChromeViewHostMsg_GetPluginInfo_Status::kUnauthorized: { + placeholder = PluginPlaceholder::CreateBlockedPlugin( + render_view, frame, params, plugin, name, + IDR_BLOCKED_PLUGIN_HTML, IDS_PLUGIN_NOT_AUTHORIZED); + placeholder->set_allow_loading(true); + render_view->Send(new ChromeViewHostMsg_BlockedUnauthorizedPlugin( + render_view->GetRoutingId(), group->GetGroupName())); + break; + } + case ChromeViewHostMsg_GetPluginInfo_Status::kClickToPlay: { + placeholder = PluginPlaceholder::CreateBlockedPlugin( + render_view, frame, params, plugin, name, + IDR_CLICK_TO_PLAY_PLUGIN_HTML, IDS_PLUGIN_LOAD); + placeholder->set_allow_loading(true); + RenderThread::Get()->RecordUserMetrics("Plugin_ClickToPlay"); + observer->DidBlockContentType(content_type, group->identifier()); + break; + } + case ChromeViewHostMsg_GetPluginInfo_Status::kBlocked: { + placeholder = PluginPlaceholder::CreateBlockedPlugin( + render_view, frame, params, plugin, name, + IDR_BLOCKED_PLUGIN_HTML, IDS_PLUGIN_BLOCKED); + placeholder->set_allow_loading(true); + RenderThread::Get()->RecordUserMetrics("Plugin_Blocked"); + observer->DidBlockContentType(content_type, group->identifier()); + break; + } + } } + placeholder->SetStatus(status); + return placeholder->plugin(); } bool ChromeContentRendererClient::IsNaClAllowed( diff --git a/chrome/renderer/plugins/blocked_plugin.cc b/chrome/renderer/plugins/blocked_plugin.cc deleted file mode 100644 index ccabb20..0000000 --- a/chrome/renderer/plugins/blocked_plugin.cc +++ /dev/null @@ -1,232 +0,0 @@ -// Copyright (c) 2012 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/blocked_plugin.h" - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/string_piece.h" -#include "base/string_util.h" -#include "base/values.h" -#include "chrome/common/jstemplate_builder.h" -#include "chrome/common/render_messages.h" -#include "chrome/renderer/custom_menu_commands.h" -#include "content/public/renderer/render_thread.h" -#include "content/public/renderer/render_view.h" -#include "grit/generated_resources.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebContextMenuData.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebMenuItemInfo.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebPoint.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebVector.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/resource/resource_bundle.h" -#include "webkit/glue/webpreferences.h" -#include "webkit/plugins/npapi/plugin_group.h" -#include "webkit/plugins/webview_plugin.h" - -using WebKit::WebContextMenuData; -using WebKit::WebFrame; -using WebKit::WebMenuItemInfo; -using WebKit::WebPlugin; -using WebKit::WebPluginParams; -using WebKit::WebPoint; -using WebKit::WebString; -using WebKit::WebURLRequest; -using WebKit::WebVector; -using content::RenderThread; -using webkit::WebViewPlugin; - -namespace { -const BlockedPlugin* g_last_active_menu = NULL; -} - -// static -WebViewPlugin* BlockedPlugin::Create(content::RenderView* render_view, - WebFrame* frame, - const WebPluginParams& params, - const webkit::WebPluginInfo& plugin, - const webkit::npapi::PluginGroup* group, - int template_id, - int message_id, - bool is_blocked_for_prerendering, - bool allow_loading) { - string16 name = group->GetGroupName(); - string16 message = l10n_util::GetStringFUTF16(message_id, name); - - DictionaryValue values; - values.SetString("message", message); - values.SetString("name", name); - values.SetString("hide", l10n_util::GetStringUTF8(IDS_PLUGIN_HIDE)); - - const base::StringPiece template_html( - ResourceBundle::GetSharedInstance().GetRawDataResource(template_id)); - - DCHECK(!template_html.empty()) << "unable to load template. ID: " - << template_id; - // "t" is the id of the templates root node. - std::string html_data = jstemplate_builder::GetI18nTemplateHtml( - template_html, &values); - - // |blocked_plugin| will destroy itself when its WebViewPlugin is going away. - BlockedPlugin* blocked_plugin = new BlockedPlugin( - render_view, frame, params, html_data, plugin, name, - is_blocked_for_prerendering, allow_loading); - return blocked_plugin->plugin(); -} - -BlockedPlugin::BlockedPlugin(content::RenderView* render_view, - WebFrame* frame, - const WebPluginParams& params, - const std::string& html_data, - const webkit::WebPluginInfo& info, - const string16& name, - bool is_blocked_for_prerendering, - bool allow_loading) - : PluginPlaceholder(render_view, frame, params, html_data), - plugin_info_(info), - name_(name), - is_blocked_for_prerendering_(is_blocked_for_prerendering), - hidden_(false), - allow_loading_(allow_loading) { -} - -BlockedPlugin::~BlockedPlugin() { -} - -void BlockedPlugin::BindWebFrame(WebFrame* frame) { - PluginPlaceholder::BindWebFrame(frame); - BindCallback("load", base::Bind(&BlockedPlugin::LoadCallback, - base::Unretained(this))); - BindCallback("hide", base::Bind(&BlockedPlugin::HideCallback, - base::Unretained(this))); - BindCallback("openAboutPlugins", - base::Bind(&BlockedPlugin::OpenAboutPluginsCallback, - base::Unretained(this))); -} - -void BlockedPlugin::ShowContextMenu(const WebKit::WebMouseEvent& event) { - WebContextMenuData menu_data; - - size_t num_items = name_.empty() ? 2u : 4u; - WebVector<WebMenuItemInfo> custom_items(num_items); - - size_t i = 0; - if (!name_.empty()) { - WebMenuItemInfo name_item; - name_item.label = name_; - name_item.hasTextDirectionOverride = false; - name_item.textDirection = WebKit::WebTextDirectionDefault; - custom_items[i++] = name_item; - - WebMenuItemInfo separator_item; - separator_item.type = WebMenuItemInfo::Separator; - custom_items[i++] = separator_item; - } - - WebMenuItemInfo run_item; - run_item.action = chrome::MENU_COMMAND_PLUGIN_RUN; - // Disable this menu item if the plugin is blocked by policy. - run_item.enabled = allow_loading_; - run_item.label = WebString::fromUTF8( - l10n_util::GetStringUTF8(IDS_CONTENT_CONTEXT_PLUGIN_RUN).c_str()); - run_item.hasTextDirectionOverride = false; - run_item.textDirection = WebKit::WebTextDirectionDefault; - custom_items[i++] = run_item; - - WebMenuItemInfo hide_item; - hide_item.action = chrome::MENU_COMMAND_PLUGIN_HIDE; - hide_item.enabled = true; - hide_item.label = WebString::fromUTF8( - l10n_util::GetStringUTF8(IDS_CONTENT_CONTEXT_PLUGIN_HIDE).c_str()); - hide_item.hasTextDirectionOverride = false; - hide_item.textDirection = WebKit::WebTextDirectionDefault; - custom_items[i++] = hide_item; - - menu_data.customItems.swap(custom_items); - menu_data.mousePosition = WebPoint(event.windowX, event.windowY); - render_view()->ShowContextMenu(NULL, menu_data); - g_last_active_menu = this; -} - -bool BlockedPlugin::OnMessageReceived(const IPC::Message& message) { - // We don't swallow ViewMsg_CustomContextMenuAction because we listen for all - // custom menu IDs, and not just our own. We don't swallow - // ViewMsg_LoadBlockedPlugins because multiple blocked plugins have an - // interest in it. - IPC_BEGIN_MESSAGE_MAP(BlockedPlugin, message) - IPC_MESSAGE_HANDLER(ChromeViewMsg_LoadBlockedPlugins, OnLoadBlockedPlugins) - IPC_MESSAGE_HANDLER(ChromeViewMsg_SetIsPrerendering, OnSetIsPrerendering) - IPC_END_MESSAGE_MAP() - - return false; -} - -void BlockedPlugin::ContextMenuAction(unsigned id) { - if (g_last_active_menu != this) - return; - switch (id) { - case chrome::MENU_COMMAND_PLUGIN_RUN: { - RenderThread::Get()->RecordUserMetrics("Plugin_Load_Menu"); - LoadPlugin(); - break; - } - case chrome::MENU_COMMAND_PLUGIN_HIDE: { - RenderThread::Get()->RecordUserMetrics("Plugin_Hide_Menu"); - HidePlugin(); - break; - } - default: - NOTREACHED(); - } -} - -void BlockedPlugin::OnLoadBlockedPlugins() { - RenderThread::Get()->RecordUserMetrics("Plugin_Load_UI"); - LoadPlugin(); -} - -void BlockedPlugin::OnSetIsPrerendering(bool is_prerendering) { - // Prerendering can only be enabled prior to a RenderView's first navigation, - // so no BlockedPlugin should see the notification that enables prerendering. - DCHECK(!is_prerendering); - if (is_blocked_for_prerendering_ && !is_prerendering) - LoadPlugin(); -} - -void BlockedPlugin::LoadPlugin() { - // This is not strictly necessary but is an important defense in case the - // event propagation changes between "close" vs. "click-to-play". - if (hidden_) - return; - if (!allow_loading_) - return; - WebPlugin* plugin = - render_view()->CreatePlugin(frame(), plugin_info_, plugin_params()); - LoadPluginInternal(plugin); -} - -void BlockedPlugin::LoadCallback(const CppArgumentList& args, - CppVariant* result) { - RenderThread::Get()->RecordUserMetrics("Plugin_Load_Click"); - LoadPlugin(); -} - -void BlockedPlugin::HideCallback(const CppArgumentList& args, - CppVariant* result) { - RenderThread::Get()->RecordUserMetrics("Plugin_Hide_Click"); - HidePlugin(); -} - -void BlockedPlugin::OpenAboutPluginsCallback(const CppArgumentList& args, - CppVariant* result) { - RenderThread::Get()->Send( - new ChromeViewHostMsg_OpenAboutPlugins(routing_id())); -} - -void BlockedPlugin::HidePlugin() { - hidden_ = true; - HidePluginInternal(); -} diff --git a/chrome/renderer/plugins/blocked_plugin.h b/chrome/renderer/plugins/blocked_plugin.h deleted file mode 100644 index 453aa93..0000000 --- a/chrome/renderer/plugins/blocked_plugin.h +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) 2012 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_RENDERER_PLUGINS_BLOCKED_PLUGIN_H_ -#define CHROME_RENDERER_PLUGINS_BLOCKED_PLUGIN_H_ -#pragma once - -#include "chrome/renderer/plugins/plugin_placeholder.h" -#include "webkit/plugins/webplugininfo.h" - -namespace webkit { -namespace npapi { -class PluginGroup; -} -} - -class BlockedPlugin : public PluginPlaceholder { - public: - // Creates a new WebViewPlugin with a BlockedPlugin as a delegate. - static webkit::WebViewPlugin* Create(content::RenderView* render_view, - WebKit::WebFrame* frame, - const WebKit::WebPluginParams& params, - const webkit::WebPluginInfo& info, - const webkit::npapi::PluginGroup* group, - int resource_id, - int message_id, - bool is_blocked_for_prerendering, - bool allow_loading); - - private: - BlockedPlugin(content::RenderView* render_view, - WebKit::WebFrame* frame, - const WebKit::WebPluginParams& params, - const std::string& html_data, - const webkit::WebPluginInfo& info, - const string16& name, - bool is_blocked_for_prerendering, - bool allow_loading); - virtual ~BlockedPlugin(); - - // WebViewPlugin::Delegate methods: - virtual void BindWebFrame(WebKit::WebFrame* frame) OVERRIDE; - virtual void ShowContextMenu(const WebKit::WebMouseEvent&) OVERRIDE; - - // RenderViewObserver methods: - virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; - virtual void ContextMenuAction(unsigned id) OVERRIDE; - - void OnLoadBlockedPlugins(); - void OnSetIsPrerendering(bool is_prerendering); - - // Javascript callbacks: - // Load the blocked plugin by calling LoadPlugin(). - // Takes no arguments, and returns nothing. - void LoadCallback(const CppArgumentList& args, CppVariant* result); - - // Hide the blocked plugin by calling HidePlugin(). - // Takes no arguments, and returns nothing. - void HideCallback(const CppArgumentList& args, CppVariant* result); - - // Opens chrome://plugins in a new tab. - // Takes no arguments, and returns nothing. - void OpenAboutPluginsCallback(const CppArgumentList& args, - CppVariant* result); - - // Load the blocked plugin. - void LoadPlugin(); - - // Hide the blocked plugin. - void HidePlugin(); - - webkit::WebPluginInfo plugin_info_; - // The name of the plugin that was blocked. - string16 name_; - // True iff the plugin was blocked because the page was being prerendered. - // Plugin will automatically be loaded when the page is displayed. - bool is_blocked_for_prerendering_; - bool hidden_; - bool allow_loading_; -}; - -#endif // CHROME_RENDERER_PLUGINS_BLOCKED_PLUGIN_H_ diff --git a/chrome/renderer/plugins/missing_plugin.cc b/chrome/renderer/plugins/missing_plugin.cc deleted file mode 100644 index 02ebbcb..0000000 --- a/chrome/renderer/plugins/missing_plugin.cc +++ /dev/null @@ -1,249 +0,0 @@ -// Copyright (c) 2012 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/missing_plugin.h" - -#include "base/bind.h" -#include "base/json/string_escape.h" -#include "base/string_piece.h" -#include "base/string_util.h" -#include "base/utf_string_conversions.h" -#include "base/values.h" -#include "chrome/common/jstemplate_builder.h" -#include "chrome/common/render_messages.h" -#include "chrome/renderer/custom_menu_commands.h" -#include "chrome/renderer/chrome_content_renderer_client.h" -#include "content/public/renderer/render_thread.h" -#include "content/public/renderer/render_view.h" -#include "grit/generated_resources.h" -#include "grit/renderer_resources.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebContextMenuData.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebMenuItemInfo.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebPoint.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebScriptSource.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebVector.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/resource/resource_bundle.h" -#include "webkit/plugins/npapi/plugin_group.h" - -using WebKit::WebContextMenuData; -using WebKit::WebFrame; -using WebKit::WebMenuItemInfo; -using WebKit::WebPlugin; -using WebKit::WebPluginParams; -using WebKit::WebPoint; -using WebKit::WebScriptSource; -using WebKit::WebString; -using WebKit::WebVector; -using content::RenderThread; -using content::RenderView; -using webkit::WebViewPlugin; - -namespace { -const MissingPlugin* g_last_active_menu = NULL; -} - -// static -WebViewPlugin* MissingPlugin::Create(RenderView* render_view, - WebFrame* frame, - const WebPluginParams& params) { - const base::StringPiece template_html( - ResourceBundle::GetSharedInstance().GetRawDataResource( - IDR_BLOCKED_PLUGIN_HTML)); - - DictionaryValue values; - values.SetString("message", l10n_util::GetStringUTF8(IDS_PLUGIN_SEARCHING)); - - // "t" is the id of the templates root node. - std::string html_data = - jstemplate_builder::GetI18nTemplateHtml(template_html, &values); - - // |missing_plugin| will destroy itself when its WebViewPlugin is going away. - MissingPlugin* missing_plugin = new MissingPlugin( - render_view, frame, params, html_data); - return missing_plugin->plugin(); -} - -MissingPlugin::MissingPlugin(RenderView* render_view, - WebFrame* frame, - const WebPluginParams& params, - const std::string& html_data) - : PluginPlaceholder(render_view, frame, params, html_data), - finished_loading_(false), - has_host_(false) { - RenderThread::Get()->AddObserver(this); -#if defined(ENABLE_PLUGIN_INSTALLATION) - placeholder_routing_id_ = RenderThread::Get()->GenerateRoutingID(); - RenderThread::Get()->AddRoute(placeholder_routing_id_, this); - RenderThread::Get()->Send(new ChromeViewHostMsg_FindMissingPlugin( - routing_id(), placeholder_routing_id_, params.mimeType.utf8())); -#else - OnDidNotFindMissingPlugin(); -#endif -} - -MissingPlugin::~MissingPlugin() { - RemoveMissingPluginHost(); - RenderThread::Get()->RemoveObserver(this); -} - -void MissingPlugin::RemoveMissingPluginHost() { -#if defined(ENABLE_PLUGIN_INSTALLATION) - if (placeholder_routing_id_ == MSG_ROUTING_NONE) - return; - RenderThread::Get()->RemoveRoute(placeholder_routing_id_); - if (has_host_) { - RenderThread::Get()->Send( - new ChromeViewHostMsg_RemoveMissingPluginHost(routing_id(), - placeholder_routing_id_)); - } - placeholder_routing_id_ = MSG_ROUTING_NONE; -#endif -} - -void MissingPlugin::BindWebFrame(WebFrame* frame) { - PluginPlaceholder::BindWebFrame(frame); - BindCallback("hide", base::Bind(&MissingPlugin::HideCallback, - base::Unretained(this))); - BindCallback("didFinishLoading", - base::Bind(&MissingPlugin::DidFinishLoadingCallback, - base::Unretained(this))); -} - -void MissingPlugin::HideCallback(const CppArgumentList& args, - CppVariant* result) { - RenderThread::Get()->RecordUserMetrics("MissingPlugin_Hide_Click"); - HidePluginInternal(); - RemoveMissingPluginHost(); -} - -void MissingPlugin::DidFinishLoadingCallback(const CppArgumentList& args, - CppVariant* result) { - finished_loading_ = true; - if (message_.length() > 0) - UpdateMessage(); -} - -void MissingPlugin::ShowContextMenu(const WebKit::WebMouseEvent& event) { - WebContextMenuData menu_data; - - WebVector<WebMenuItemInfo> custom_items(static_cast<size_t>(3)); - - size_t i = 0; - WebMenuItemInfo mime_type_item; - mime_type_item.label = plugin_params().mimeType; - mime_type_item.hasTextDirectionOverride = false; - mime_type_item.textDirection = WebKit::WebTextDirectionDefault; - custom_items[i++] = mime_type_item; - - WebMenuItemInfo separator_item; - separator_item.type = WebMenuItemInfo::Separator; - custom_items[i++] = separator_item; - - WebMenuItemInfo hide_item; - hide_item.action = chrome::MENU_COMMAND_PLUGIN_HIDE; - hide_item.enabled = true; - hide_item.label = WebString::fromUTF8( - l10n_util::GetStringUTF8(IDS_CONTENT_CONTEXT_PLUGIN_HIDE).c_str()); - hide_item.hasTextDirectionOverride = false; - hide_item.textDirection = WebKit::WebTextDirectionDefault; - custom_items[i++] = hide_item; - - menu_data.customItems.swap(custom_items); - menu_data.mousePosition = WebPoint(event.windowX, event.windowY); - render_view()->ShowContextMenu(NULL, menu_data); - g_last_active_menu = this; -} - -#if defined(ENABLE_PLUGIN_INSTALLATION) -bool MissingPlugin::OnMessageReceived(const IPC::Message& message) { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(MissingPlugin, message) - IPC_MESSAGE_HANDLER(ChromeViewMsg_FoundMissingPlugin, - OnFoundMissingPlugin) - IPC_MESSAGE_HANDLER(ChromeViewMsg_DidNotFindMissingPlugin, - OnDidNotFindMissingPlugin) - IPC_MESSAGE_HANDLER(ChromeViewMsg_StartedDownloadingPlugin, - OnStartedDownloadingPlugin) - IPC_MESSAGE_HANDLER(ChromeViewMsg_FinishedDownloadingPlugin, - OnFinishedDownloadingPlugin) - IPC_MESSAGE_HANDLER(ChromeViewMsg_ErrorDownloadingPlugin, - OnErrorDownloadingPlugin) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - - return handled; -} -#endif // defined(ENABLE_PLUGIN_INSTALLATION) - -void MissingPlugin::OnDidNotFindMissingPlugin() { - SetMessage(l10n_util::GetStringUTF16(IDS_PLUGIN_NOT_FOUND)); -} - -#if defined(ENABLE_PLUGIN_INSTALLATION) -void MissingPlugin::OnFoundMissingPlugin(const string16& plugin_name) { - SetMessage(l10n_util::GetStringFUTF16(IDS_PLUGIN_FOUND, plugin_name)); - has_host_ = true; -} - -void MissingPlugin::OnStartedDownloadingPlugin() { - SetMessage(l10n_util::GetStringUTF16(IDS_PLUGIN_DOWNLOADING)); -} - -void MissingPlugin::OnFinishedDownloadingPlugin() { - SetMessage(l10n_util::GetStringUTF16(IDS_PLUGIN_INSTALLING)); -} - -void MissingPlugin::OnErrorDownloadingPlugin(const std::string& error) { - SetMessage(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOAD_ERROR, - UTF8ToUTF16(error))); -} -#endif // defined(ENABLE_PLUGIN_INSTALLATION) - -void MissingPlugin::PluginListChanged() { - ChromeViewHostMsg_GetPluginInfo_Status status; - webkit::WebPluginInfo plugin_info; - std::string mime_type(plugin_params().mimeType.utf8()); - std::string actual_mime_type; - render_view()->Send(new ChromeViewHostMsg_GetPluginInfo( - routing_id(), GURL(plugin_params().url), frame()->top()->document().url(), - mime_type, &status, &plugin_info, &actual_mime_type)); - if (status.value == ChromeViewHostMsg_GetPluginInfo_Status::kNotFound) - return; - chrome::ChromeContentRendererClient* client = - static_cast<chrome::ChromeContentRendererClient*>( - content::GetContentClient()->renderer()); - WebPlugin* new_plugin = - client->CreatePlugin(render_view(), frame(), plugin_params(), - status, plugin_info, actual_mime_type); - LoadPluginInternal(new_plugin); -} - -void MissingPlugin::SetMessage(const string16& message) { - message_ = message; - if (finished_loading_) - UpdateMessage(); -} - -void MissingPlugin::UpdateMessage() { - std::string script = "window.setMessage(" + - base::GetDoubleQuotedJson(message_) + ")"; - plugin()->web_view()->mainFrame()->executeScript( - WebScriptSource(ASCIIToUTF16(script))); -} - -void MissingPlugin::ContextMenuAction(unsigned id) { - if (g_last_active_menu != this) - return; - if (id == chrome::MENU_COMMAND_PLUGIN_HIDE) { - RenderThread::Get()->RecordUserMetrics("MissingPlugin_Hide_Menu"); - HidePluginInternal(); - } else { - NOTREACHED(); - } -} diff --git a/chrome/renderer/plugins/missing_plugin.h b/chrome/renderer/plugins/missing_plugin.h deleted file mode 100644 index 88af7a5..0000000 --- a/chrome/renderer/plugins/missing_plugin.h +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) 2012 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_RENDERER_PLUGINS_MISSING_PLUGIN_H_ -#define CHROME_RENDERER_PLUGINS_MISSING_PLUGIN_H_ -#pragma once - -#include "base/string16.h" -#include "chrome/renderer/plugins/plugin_placeholder.h" -#include "content/public/renderer/render_process_observer.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" - -namespace content { -class RenderThread; -} - -class MissingPlugin : public PluginPlaceholder, - public content::RenderProcessObserver { - public: - // Creates a new WebViewPlugin with a MissingPlugin as a delegate. - static webkit::WebViewPlugin* Create( - content::RenderView* render_view, - WebKit::WebFrame* frame, - const WebKit::WebPluginParams& params); - - // WebViewPlugin::Delegate methods: - virtual void BindWebFrame(WebKit::WebFrame* frame) OVERRIDE; - virtual void ShowContextMenu(const WebKit::WebMouseEvent&) OVERRIDE; - -#if defined(ENABLE_PLUGIN_INSTALLATION) - // IPC::Channel::Listener methods: - virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; -#endif - - // content::RenderViewObserver methods: - virtual void ContextMenuAction(unsigned id) OVERRIDE; - - // content::RenderProcessObserver methods: - virtual void PluginListChanged() OVERRIDE; - - private: - MissingPlugin(content::RenderView* render_view, - WebKit::WebFrame* frame, - const WebKit::WebPluginParams& params, - const std::string& html_data); - virtual ~MissingPlugin(); - - void HideCallback(const CppArgumentList& args, CppVariant* result); - void DidFinishLoadingCallback(const CppArgumentList& args, - CppVariant* result); - - void OnDidNotFindMissingPlugin(); -#if defined(ENABLE_PLUGIN_INSTALLATION) - void OnFoundMissingPlugin(const string16& plugin_name); - void OnStartedDownloadingPlugin(); - void OnFinishedDownloadingPlugin(); - void OnErrorDownloadingPlugin(const std::string& error); -#endif - - void SetMessage(const string16& message); - void UpdateMessage(); - - void RemoveMissingPluginHost(); - -#if defined(ENABLE_PLUGIN_INSTALLATION) - // |routing_id()| is the routing ID of our associated RenderView, but we have - // a separate routing ID for messages specific to this placeholder. - int32 placeholder_routing_id_; -#endif - - bool finished_loading_; - bool has_host_; - string16 message_; - - DISALLOW_COPY_AND_ASSIGN(MissingPlugin); -}; - -#endif // CHROME_RENDERER_PLUGINS_MISSING_PLUGIN_H_ diff --git a/chrome/renderer/plugins/plugin_placeholder.cc b/chrome/renderer/plugins/plugin_placeholder.cc index 7bceea5..87d8b0c 100644 --- a/chrome/renderer/plugins/plugin_placeholder.cc +++ b/chrome/renderer/plugins/plugin_placeholder.cc @@ -4,53 +4,224 @@ #include "chrome/renderer/plugins/plugin_placeholder.h" +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/json/string_escape.h" +#include "base/string_piece.h" #include "base/string_util.h" +#include "base/utf_string_conversions.h" +#include "base/values.h" +#include "chrome/common/jstemplate_builder.h" +#include "chrome/common/render_messages.h" +#include "chrome/renderer/chrome_content_renderer_client.h" +#include "chrome/renderer/custom_menu_commands.h" #include "chrome/renderer/plugins/plugin_uma.h" +#include "content/public/renderer/render_thread.h" #include "content/public/renderer/render_view.h" +#include "grit/generated_resources.h" +#include "grit/renderer_resources.h" #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebData.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebPoint.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebVector.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebContextMenuData.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebMenuItemInfo.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginContainer.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebRegularExpression.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebScriptSource.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebTextCaseSensitivity.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/resource/resource_bundle.h" +#include "webkit/glue/webpreferences.h" +#include "webkit/plugins/npapi/plugin_group.h" +#include "webkit/plugins/webview_plugin.h" +using content::RenderThread; +using content::RenderView; +using WebKit::WebContextMenuData; using WebKit::WebElement; using WebKit::WebFrame; +using WebKit::WebMenuItemInfo; using WebKit::WebMouseEvent; using WebKit::WebNode; using WebKit::WebPlugin; using WebKit::WebPluginContainer; +using webkit::WebPluginInfo; using WebKit::WebPluginParams; +using WebKit::WebPoint; using WebKit::WebRegularExpression; +using WebKit::WebScriptSource; using WebKit::WebString; -using webkit::WebPluginInfo; +using WebKit::WebURLRequest; +using WebKit::WebVector; using webkit::WebViewPlugin; -static const char* const kPluginPlaceholderDataURL = +const char* const kPluginPlaceholderDataURL = "chrome://pluginplaceholderdata/"; +namespace { +const PluginPlaceholder* g_last_active_menu = NULL; +} + +// static +PluginPlaceholder* PluginPlaceholder::CreateMissingPlugin( + RenderView* render_view, + WebFrame* frame, + const WebPluginParams& params) { + const base::StringPiece template_html( + ResourceBundle::GetSharedInstance().GetRawDataResource( + IDR_BLOCKED_PLUGIN_HTML)); + + DictionaryValue values; + values.SetString("message", l10n_util::GetStringUTF8(IDS_PLUGIN_SEARCHING)); + + std::string html_data = + jstemplate_builder::GetI18nTemplateHtml(template_html, &values); + + // |missing_plugin| will destroy itself when its WebViewPlugin is going away. + PluginPlaceholder* missing_plugin = new PluginPlaceholder( + render_view, frame, params, html_data, params.mimeType); + missing_plugin->set_allow_loading(true); +#if defined(ENABLE_PLUGIN_INSTALLATION) + RenderThread::Get()->Send(new ChromeViewHostMsg_FindMissingPlugin( + missing_plugin->routing_id(), missing_plugin->CreateRoutingId(), + params.mimeType.utf8())); +#else + OnDidNotFindMissingPlugin(); +#endif + return missing_plugin; +} + +// static +PluginPlaceholder* PluginPlaceholder::CreateBlockedPlugin( + RenderView* render_view, + WebFrame* frame, + const WebPluginParams& params, + const WebPluginInfo& plugin, + const string16& name, + int template_id, + int message_id) { + string16 message = l10n_util::GetStringFUTF16(message_id, name); + + DictionaryValue values; + values.SetString("message", message); + values.SetString("name", name); + values.SetString("hide", l10n_util::GetStringUTF8(IDS_PLUGIN_HIDE)); + + const base::StringPiece template_html( + ResourceBundle::GetSharedInstance().GetRawDataResource(template_id)); + + DCHECK(!template_html.empty()) << "unable to load template. ID: " + << template_id; + std::string html_data = jstemplate_builder::GetI18nTemplateHtml( + template_html, &values); + + // |blocked_plugin| will destroy itself when its WebViewPlugin is going away. + PluginPlaceholder* blocked_plugin = new PluginPlaceholder( + render_view, frame, params, html_data, name); + blocked_plugin->plugin_info_ = plugin; + return blocked_plugin; +} + PluginPlaceholder::PluginPlaceholder(content::RenderView* render_view, WebFrame* frame, const WebPluginParams& params, - const std::string& html_data) + const std::string& html_data, + const string16& title) : content::RenderViewObserver(render_view), frame_(frame), plugin_params_(params), plugin_(WebViewPlugin::Create( this, render_view->GetWebkitPreferences(), html_data, - GURL(kPluginPlaceholderDataURL))) { + GURL(kPluginPlaceholderDataURL))), + title_(title), + status_(new ChromeViewHostMsg_GetPluginInfo_Status), + is_blocked_for_prerendering_(false), + allow_loading_(false), +#if defined(ENABLE_PLUGIN_INSTALLATION) + placeholder_routing_id_(MSG_ROUTING_NONE), +#endif + hidden_(false), + has_host_(false), + finished_loading_(false) { + RenderThread::Get()->AddObserver(this); } PluginPlaceholder::~PluginPlaceholder() { + RenderThread::Get()->RemoveObserver(this); +#if defined(ENABLE_PLUGIN_INSTALLATION) + if (placeholder_routing_id_ == MSG_ROUTING_NONE) + return; + RenderThread::Get()->RemoveRoute(placeholder_routing_id_); + if (has_host_) { + RenderThread::Get()->Send( + new ChromeViewHostMsg_RemovePluginPlaceholderHost( + routing_id(), placeholder_routing_id_)); + } +#endif +} + +#if defined(ENABLE_PLUGIN_INSTALLATION) +int32 PluginPlaceholder::CreateRoutingId() { + placeholder_routing_id_ = RenderThread::Get()->GenerateRoutingID(); + RenderThread::Get()->AddRoute(placeholder_routing_id_, this); + return placeholder_routing_id_; +} +#endif + +void PluginPlaceholder::SetStatus( + const ChromeViewHostMsg_GetPluginInfo_Status& status) { + status_->value = status.value; } void PluginPlaceholder::BindWebFrame(WebFrame* frame) { BindToJavascript(frame, "plugin"); + BindCallback("load", base::Bind(&PluginPlaceholder::LoadCallback, + base::Unretained(this))); + BindCallback("hide", base::Bind(&PluginPlaceholder::HideCallback, + base::Unretained(this))); + BindCallback("openAboutPlugins", + base::Bind(&PluginPlaceholder::OpenAboutPluginsCallback, + base::Unretained(this))); + BindCallback("didFinishLoading", + base::Bind(&PluginPlaceholder::DidFinishLoadingCallback, + base::Unretained(this))); } -void PluginPlaceholder::LoadPluginInternal(WebPlugin* new_plugin) { +bool PluginPlaceholder::OnMessageReceived(const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(PluginPlaceholder, message) + IPC_MESSAGE_HANDLER(ChromeViewMsg_FoundMissingPlugin, + OnFoundMissingPlugin) + IPC_MESSAGE_HANDLER(ChromeViewMsg_DidNotFindMissingPlugin, + OnDidNotFindMissingPlugin) + IPC_MESSAGE_HANDLER(ChromeViewMsg_StartedDownloadingPlugin, + OnStartedDownloadingPlugin) + IPC_MESSAGE_HANDLER(ChromeViewMsg_FinishedDownloadingPlugin, + OnFinishedDownloadingPlugin) + IPC_MESSAGE_HANDLER(ChromeViewMsg_ErrorDownloadingPlugin, + OnErrorDownloadingPlugin) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + + if (handled) + return true; + + // We don't swallow these messages because multiple blocked plugins have an + // interest in them. + IPC_BEGIN_MESSAGE_MAP(PluginPlaceholder, message) + IPC_MESSAGE_HANDLER(ChromeViewMsg_LoadBlockedPlugins, OnLoadBlockedPlugins) + IPC_MESSAGE_HANDLER(ChromeViewMsg_SetIsPrerendering, OnSetIsPrerendering) + IPC_END_MESSAGE_MAP() + + return false; +} + +void PluginPlaceholder::ReplacePlugin(WebPlugin* new_plugin) { CHECK(plugin_); WebPluginContainer* container = plugin_->container(); if (new_plugin && new_plugin->initialize(container)) { @@ -67,7 +238,8 @@ void PluginPlaceholder::LoadPluginInternal(WebPlugin* new_plugin) { } } -void PluginPlaceholder::HidePluginInternal() { +void PluginPlaceholder::HidePlugin() { + hidden_ = true; WebPluginContainer* container = plugin_->container(); WebElement element = container->element(); element.setAttribute("style", "display: none;"); @@ -120,5 +292,177 @@ void PluginPlaceholder::WillDestroyPlugin() { delete this; } +void PluginPlaceholder::OnDidNotFindMissingPlugin() { + SetMessage(l10n_util::GetStringUTF16(IDS_PLUGIN_NOT_FOUND)); +} + +#if defined(ENABLE_PLUGIN_INSTALLATION) +void PluginPlaceholder::OnFoundMissingPlugin(const string16& plugin_name) { + if (status_->value == ChromeViewHostMsg_GetPluginInfo_Status::kNotFound) + SetMessage(l10n_util::GetStringFUTF16(IDS_PLUGIN_FOUND, plugin_name)); + has_host_ = true; +} + +void PluginPlaceholder::OnStartedDownloadingPlugin() { + SetMessage(l10n_util::GetStringUTF16(IDS_PLUGIN_DOWNLOADING)); +} + +void PluginPlaceholder::OnFinishedDownloadingPlugin() { + SetMessage(l10n_util::GetStringUTF16(IDS_PLUGIN_INSTALLING)); +} + +void PluginPlaceholder::OnErrorDownloadingPlugin(const std::string& error) { + SetMessage(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOAD_ERROR, + UTF8ToUTF16(error))); +} +#endif // defined(ENABLE_PLUGIN_INSTALLATION) + +void PluginPlaceholder::PluginListChanged() { + ChromeViewHostMsg_GetPluginInfo_Status status; + webkit::WebPluginInfo plugin_info; + std::string mime_type(plugin_params_.mimeType.utf8()); + std::string actual_mime_type; + render_view()->Send(new ChromeViewHostMsg_GetPluginInfo( + routing_id(), GURL(plugin_params_.url), frame_->top()->document().url(), + mime_type, &status, &plugin_info, &actual_mime_type)); + if (status.value == status_->value) + return; + chrome::ChromeContentRendererClient* client = + static_cast<chrome::ChromeContentRendererClient*>( + content::GetContentClient()->renderer()); + WebPlugin* new_plugin = + client->CreatePlugin(render_view(), frame_, plugin_params_, + status, plugin_info, actual_mime_type); + ReplacePlugin(new_plugin); +} + +void PluginPlaceholder::SetMessage(const string16& message) { + message_ = message; + if (finished_loading_) + UpdateMessage(); +} + +void PluginPlaceholder::UpdateMessage() { + std::string script = "window.setMessage(" + + base::GetDoubleQuotedJson(message_) + ")"; + plugin_->web_view()->mainFrame()->executeScript( + WebScriptSource(ASCIIToUTF16(script))); +} + +void PluginPlaceholder::ContextMenuAction(unsigned id) { + if (g_last_active_menu != this) + return; + switch (id) { + case chrome::MENU_COMMAND_PLUGIN_RUN: { + RenderThread::Get()->RecordUserMetrics("Plugin_Load_Menu"); + LoadPlugin(); + break; + } + case chrome::MENU_COMMAND_PLUGIN_HIDE: { + RenderThread::Get()->RecordUserMetrics("Plugin_Hide_Menu"); + HidePlugin(); + break; + } + default: + NOTREACHED(); + } +} + void PluginPlaceholder::ShowContextMenu(const WebMouseEvent& event) { + WebContextMenuData menu_data; + + size_t num_items = 3u; + if (!plugin_info_.path.value().empty()) + num_items++; + + WebVector<WebMenuItemInfo> custom_items(num_items); + + size_t i = 0; + WebMenuItemInfo name_item; + name_item.label = title_; + name_item.hasTextDirectionOverride = false; + name_item.textDirection = WebKit::WebTextDirectionDefault; + custom_items[i++] = name_item; + + WebMenuItemInfo separator_item; + separator_item.type = WebMenuItemInfo::Separator; + custom_items[i++] = separator_item; + + if (!plugin_info_.path.value().empty()) { + WebMenuItemInfo run_item; + run_item.action = chrome::MENU_COMMAND_PLUGIN_RUN; + // Disable this menu item if the plugin is blocked by policy. + run_item.enabled = allow_loading_; + run_item.label = WebString::fromUTF8( + l10n_util::GetStringUTF8(IDS_CONTENT_CONTEXT_PLUGIN_RUN).c_str()); + run_item.hasTextDirectionOverride = false; + run_item.textDirection = WebKit::WebTextDirectionDefault; + custom_items[i++] = run_item; + } + + WebMenuItemInfo hide_item; + hide_item.action = chrome::MENU_COMMAND_PLUGIN_HIDE; + hide_item.enabled = true; + hide_item.label = WebString::fromUTF8( + l10n_util::GetStringUTF8(IDS_CONTENT_CONTEXT_PLUGIN_HIDE).c_str()); + hide_item.hasTextDirectionOverride = false; + hide_item.textDirection = WebKit::WebTextDirectionDefault; + custom_items[i++] = hide_item; + + menu_data.customItems.swap(custom_items); + menu_data.mousePosition = WebPoint(event.windowX, event.windowY); + render_view()->ShowContextMenu(NULL, menu_data); + g_last_active_menu = this; +} + +void PluginPlaceholder::OnLoadBlockedPlugins() { + RenderThread::Get()->RecordUserMetrics("Plugin_Load_UI"); + LoadPlugin(); +} + +void PluginPlaceholder::OnSetIsPrerendering(bool is_prerendering) { + // Prerendering can only be enabled prior to a RenderView's first navigation, + // so no BlockedPlugin should see the notification that enables prerendering. + DCHECK(!is_prerendering); + if (is_blocked_for_prerendering_ && !is_prerendering) + LoadPlugin(); +} + +void PluginPlaceholder::LoadPlugin() { + // This is not strictly necessary but is an important defense in case the + // event propagation changes between "close" vs. "click-to-play". + if (hidden_) + return; + if (!allow_loading_) { + NOTREACHED(); + return; + } + WebPlugin* plugin = + render_view()->CreatePlugin(frame_, plugin_info_, plugin_params_); + ReplacePlugin(plugin); +} + +void PluginPlaceholder::LoadCallback(const CppArgumentList& args, + CppVariant* result) { + RenderThread::Get()->RecordUserMetrics("Plugin_Load_Click"); + LoadPlugin(); +} + +void PluginPlaceholder::HideCallback(const CppArgumentList& args, + CppVariant* result) { + RenderThread::Get()->RecordUserMetrics("Plugin_Hide_Click"); + HidePlugin(); +} + +void PluginPlaceholder::OpenAboutPluginsCallback(const CppArgumentList& args, + CppVariant* result) { + RenderThread::Get()->Send( + new ChromeViewHostMsg_OpenAboutPlugins(routing_id())); +} + +void PluginPlaceholder::DidFinishLoadingCallback(const CppArgumentList& args, + CppVariant* result) { + finished_loading_ = true; + if (message_.length() > 0) + UpdateMessage(); } diff --git a/chrome/renderer/plugins/plugin_placeholder.h b/chrome/renderer/plugins/plugin_placeholder.h index f6c9675..3034c6b 100644 --- a/chrome/renderer/plugins/plugin_placeholder.h +++ b/chrome/renderer/plugins/plugin_placeholder.h @@ -6,51 +6,149 @@ #define CHROME_RENDERER_PLUGINS_PLUGIN_PLACEHOLDER_H_ #pragma once +#include "content/public/renderer/render_process_observer.h" #include "content/public/renderer/render_view_observer.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginParams.h" #include "webkit/glue/cpp_bound_class.h" +#include "webkit/plugins/webplugininfo.h" #include "webkit/plugins/webview_plugin.h" +struct ChromeViewHostMsg_GetPluginInfo_Status; + namespace webkit { struct WebPluginInfo; +namespace npapi { +class PluginGroup; +} } -// Base class to share code between different plug-in placeholders -// used in Chrome. Placeholders can be used if a plug-in is missing or not -// available (blocked or disabled). +// Placeholders can be used if a plug-in is missing or not available +// (blocked or disabled). class PluginPlaceholder : public content::RenderViewObserver, + public content::RenderProcessObserver, public CppBoundClass, public webkit::WebViewPlugin::Delegate { - protected: + public: + // Creates a new WebViewPlugin with a MissingPlugin as a delegate. + static PluginPlaceholder* CreateMissingPlugin( + content::RenderView* render_view, + WebKit::WebFrame* frame, + const WebKit::WebPluginParams& params); + + static PluginPlaceholder* CreateBlockedPlugin( + content::RenderView* render_view, + WebKit::WebFrame* frame, + const WebKit::WebPluginParams& params, + const webkit::WebPluginInfo& info, + const string16& name, + int resource_id, + int message_id); + + webkit::WebViewPlugin* plugin() { return plugin_; } + + void set_blocked_for_prerendering(bool blocked_for_prerendering) { + is_blocked_for_prerendering_ = blocked_for_prerendering; + } + + void set_allow_loading(bool allow_loading) { allow_loading_ = allow_loading; } + + void SetStatus(const ChromeViewHostMsg_GetPluginInfo_Status& status); + +#if defined(ENABLE_PLUGIN_INSTALLATION) + int32 CreateRoutingId(); +#endif + + private: // |render_view| and |frame| are weak pointers. If either one is going away, // our |plugin_| will be destroyed as well and will notify us. PluginPlaceholder(content::RenderView* render_view, WebKit::WebFrame* frame, const WebKit::WebPluginParams& params, - const std::string& html_data); - virtual ~PluginPlaceholder(); - - webkit::WebViewPlugin* plugin() { return plugin_; } - WebKit::WebFrame* frame() { return frame_; } - const WebKit::WebPluginParams& plugin_params() { return plugin_params_; } + const std::string& html_data, + const string16& title); - // Can be called by a subclass to replace this placeholder with a different - // plugin (which could be a placeholder again). - void LoadPluginInternal(WebKit::WebPlugin* new_plugin); + virtual ~PluginPlaceholder(); // WebViewPlugin::Delegate methods: - // Can be called by a subclass to hide this placeholder. - void HidePluginInternal(); - virtual void BindWebFrame(WebKit::WebFrame* frame) OVERRIDE; virtual void WillDestroyPlugin() OVERRIDE; - virtual void ShowContextMenu(const WebKit::WebMouseEvent& event) OVERRIDE; + virtual void ShowContextMenu(const WebKit::WebMouseEvent&) OVERRIDE; + + // content::RenderViewObserver methods: + virtual void ContextMenuAction(unsigned id) OVERRIDE; + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; + + // content::RenderProcessObserver methods: + virtual void PluginListChanged() OVERRIDE; + + // Replace this placeholder with a different plugin (which could be + // a placeholder again). + void ReplacePlugin(WebKit::WebPlugin* new_plugin); + + // Hide this placeholder. + void HidePlugin(); + + // Load the blocked plugin. + void LoadPlugin(); + + // Javascript callbacks: + // Load the blocked plugin by calling LoadPlugin(). + // Takes no arguments, and returns nothing. + void LoadCallback(const CppArgumentList& args, CppVariant* result); + + // Hide the blocked plugin by calling HidePlugin(). + // Takes no arguments, and returns nothing. + void HideCallback(const CppArgumentList& args, CppVariant* result); + + // Opens chrome://plugins in a new tab. + // Takes no arguments, and returns nothing. + void OpenAboutPluginsCallback(const CppArgumentList& args, + CppVariant* result); + + void DidFinishLoadingCallback(const CppArgumentList& args, + CppVariant* result); + + void OnLoadBlockedPlugins(); + void OnSetIsPrerendering(bool is_prerendering); + void OnDidNotFindMissingPlugin(); +#if defined(ENABLE_PLUGIN_INSTALLATION) + void OnFoundMissingPlugin(const string16& plugin_name); + void OnStartedDownloadingPlugin(); + void OnFinishedDownloadingPlugin(); + void OnErrorDownloadingPlugin(const std::string& error); +#endif + + void SetMessage(const string16& message); + void UpdateMessage(); - private: WebKit::WebFrame* frame_; WebKit::WebPluginParams plugin_params_; webkit::WebViewPlugin* plugin_; + webkit::WebPluginInfo plugin_info_; + + string16 title_; + string16 message_; + + // We use a scoped_ptr so we can forward-declare the struct; it's defined in + // an IPC message file which can't be easily included in other header files. + scoped_ptr<ChromeViewHostMsg_GetPluginInfo_Status> status_; + + // True iff the plugin was blocked because the page was being prerendered. + // Plugin will automatically be loaded when the page is displayed. + bool is_blocked_for_prerendering_; + bool allow_loading_; + +#if defined(ENABLE_PLUGIN_INSTALLATION) + // |routing_id()| is the routing ID of our associated RenderView, but we have + // a separate routing ID for messages specific to this placeholder. + int32 placeholder_routing_id_; +#endif + + bool hidden_; + bool has_host_; + bool finished_loading_; + DISALLOW_COPY_AND_ASSIGN(PluginPlaceholder); }; |