diff options
author | bauerb@chromium.org <bauerb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-25 13:14:15 +0000 |
---|---|---|
committer | bauerb@chromium.org <bauerb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-25 13:14:15 +0000 |
commit | f5478b310ce3590b5555321cef0574f50d81bb1d (patch) | |
tree | c31f531ee6ceaee4485cf19e806a2d672d8cf3c6 /chrome/renderer | |
parent | 8ba31633bccd99b21ede99797d77933c673fe136 (diff) | |
download | chromium_src-f5478b310ce3590b5555321cef0574f50d81bb1d.zip chromium_src-f5478b310ce3590b5555321cef0574f50d81bb1d.tar.gz chromium_src-f5478b310ce3590b5555321cef0574f50d81bb1d.tar.bz2 |
Clean up plug-in placeholders:
* Add separate class for missing plug-in placeholder, and factor out a common base class
* Move plug-in related classes to plugins/ subdirectory
* Move custom menu command IDs to a separate header file.
TBR=darin@chromium.org
BUG=62079
TEST=none
Review URL: http://codereview.chromium.org/8461011
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@111589 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/renderer')
-rw-r--r-- | chrome/renderer/chrome_content_renderer_client.cc | 76 | ||||
-rw-r--r-- | chrome/renderer/chrome_content_renderer_client.h | 11 | ||||
-rw-r--r-- | chrome/renderer/custom_menu_commands.h | 18 | ||||
-rw-r--r-- | chrome/renderer/plugins/blocked_plugin.cc (renamed from chrome/renderer/blocked_plugin.cc) | 186 | ||||
-rw-r--r-- | chrome/renderer/plugins/blocked_plugin.h (renamed from chrome/renderer/blocked_plugin.h) | 49 | ||||
-rw-r--r-- | chrome/renderer/plugins/missing_plugin.cc | 124 | ||||
-rw-r--r-- | chrome/renderer/plugins/missing_plugin.h | 41 | ||||
-rw-r--r-- | chrome/renderer/plugins/plugin_placeholder.cc | 126 | ||||
-rw-r--r-- | chrome/renderer/plugins/plugin_placeholder.h | 56 | ||||
-rw-r--r-- | chrome/renderer/plugins/plugin_uma.cc (renamed from chrome/renderer/plugin_uma.cc) | 2 | ||||
-rw-r--r-- | chrome/renderer/plugins/plugin_uma.h (renamed from chrome/renderer/plugin_uma.h) | 6 | ||||
-rw-r--r-- | chrome/renderer/plugins/plugin_uma_unittest.cc (renamed from chrome/renderer/plugin_uma_unittest.cc) | 2 |
12 files changed, 478 insertions, 219 deletions
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index 73c5543..d238d28 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc @@ -28,7 +28,6 @@ #include "chrome/renderer/autofill/password_autofill_manager.h" #include "chrome/renderer/automation/automation_renderer_helper.h" #include "chrome/renderer/benchmarking_extension.h" -#include "chrome/renderer/blocked_plugin.h" #include "chrome/renderer/chrome_ppapi_interfaces.h" #include "chrome/renderer/chrome_render_process_observer.h" #include "chrome/renderer/chrome_render_view_observer.h" @@ -46,7 +45,9 @@ #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/plugin_uma.h" +#include "chrome/renderer/plugins/blocked_plugin.h" +#include "chrome/renderer/plugins/missing_plugin.h" +#include "chrome/renderer/plugins/plugin_uma.h" #include "chrome/renderer/prerender/prerender_helper.h" #include "chrome/renderer/print_web_view_helper.h" #include "chrome/renderer/renderer_histogram_snapshots.h" @@ -290,9 +291,7 @@ WebPlugin* ChromeContentRendererClient::CreatePlugin( if (status.value == ChromeViewHostMsg_GetPluginInfo_Status::kNotFound) { MissingPluginReporter::GetInstance()->ReportPluginMissing( orig_mime_type, url); - return CreatePluginPlaceholder( - render_view, frame, plugin, original_params, NULL, - IDR_BLOCKED_PLUGIN_HTML, IDS_PLUGIN_NOT_FOUND, false, false); + return MissingPlugin::Create(render_view, frame, original_params); } if (plugin.path.value() == webkit::npapi::kDefaultPluginLibraryName) { MissingPluginReporter::GetInstance()->ReportPluginMissing( @@ -303,8 +302,8 @@ WebPlugin* ChromeContentRendererClient::CreatePlugin( webkit::npapi::PluginList::Singleton()->GetPluginGroup(plugin)); if (status.value == ChromeViewHostMsg_GetPluginInfo_Status::kDisabled) { - return CreatePluginPlaceholder( - render_view, frame, plugin, original_params, group.get(), + return BlockedPlugin::Create( + render_view, frame, original_params, plugin, group.get(), IDR_DISABLED_PLUGIN_HTML, IDS_PLUGIN_DISABLED, false, false); } @@ -326,14 +325,14 @@ WebPlugin* ChromeContentRendererClient::CreatePlugin( GURL(group->GetUpdateURL()))); } if (status.value == - ChromeViewHostMsg_GetPluginInfo_Status::kOutdatedBlocked || + ChromeViewHostMsg_GetPluginInfo_Status::kOutdatedBlocked || status.value == ChromeViewHostMsg_GetPluginInfo_Status::kOutdatedDisallowed) { - return CreatePluginPlaceholder( - render_view, frame, plugin, params, group.get(), + return BlockedPlugin::Create( + render_view, frame, params, plugin, group.get(), IDR_BLOCKED_PLUGIN_HTML, IDS_PLUGIN_OUTDATED, false, status.value == - ChromeViewHostMsg_GetPluginInfo_Status::kOutdatedBlocked); + ChromeViewHostMsg_GetPluginInfo_Status::kOutdatedBlocked); } ContentSettingsObserver* observer = ContentSettingsObserver::Get(render_view); @@ -343,8 +342,8 @@ WebPlugin* ChromeContentRendererClient::CreatePlugin( !observer->plugins_temporarily_allowed()) { render_view->Send(new ChromeViewHostMsg_BlockedOutdatedPlugin( render_view->GetRoutingId(), group->GetGroupName(), GURL())); - return CreatePluginPlaceholder( - render_view, frame, plugin, params, group.get(), + return BlockedPlugin::Create( + render_view, frame, params, plugin, group.get(), IDR_BLOCKED_PLUGIN_HTML, IDS_PLUGIN_NOT_AUTHORIZED, false, true); } @@ -355,8 +354,8 @@ WebPlugin* ChromeContentRendererClient::CreatePlugin( plugin.path.value() == webkit::npapi::kDefaultPluginLibraryName) { // Delay loading plugins if prerendering. if (prerender::PrerenderHelper::IsPrerendering(render_view)) { - return CreatePluginPlaceholder( - render_view, frame, plugin, params, group.get(), + return BlockedPlugin::Create( + render_view, frame, params, plugin, group.get(), IDR_CLICK_TO_PLAY_PLUGIN_HTML, IDS_PLUGIN_LOAD, true, true); } @@ -381,8 +380,8 @@ WebPlugin* ChromeContentRendererClient::CreatePlugin( is_nacl_mime_type, is_nacl_enabled, params)) { - return CreatePluginPlaceholder( - render_view, frame, plugin, params, group.get(), + return BlockedPlugin::Create( + render_view, frame, params, plugin, group.get(), IDR_BLOCKED_PLUGIN_HTML, IDS_PLUGIN_BLOCKED, false, false); } } @@ -396,14 +395,14 @@ WebPlugin* ChromeContentRendererClient::CreatePlugin( group->identifier()); if (status.value == ChromeViewHostMsg_GetPluginInfo_Status::kClickToPlay) { RenderThread::Get()->RecordUserMetrics("Plugin_ClickToPlay"); - return CreatePluginPlaceholder( - render_view, frame, plugin, params, group.get(), + 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 CreatePluginPlaceholder( - render_view, frame, plugin, params, group.get(), + return BlockedPlugin::Create( + render_view, frame, params, plugin, group.get(), IDR_BLOCKED_PLUGIN_HTML, IDS_PLUGIN_BLOCKED, false, true); } } @@ -489,41 +488,6 @@ bool ChromeContentRendererClient::IsNaClAllowed( return true; } -WebPlugin* ChromeContentRendererClient::CreatePluginPlaceholder( - content::RenderView* render_view, - WebFrame* frame, - const webkit::WebPluginInfo& plugin, - const WebPluginParams& params, - const webkit::npapi::PluginGroup* group, - int resource_id, - int message_id, - bool is_blocked_for_prerendering, - bool allow_loading) { - // |blocked_plugin| will delete itself when the WebViewPlugin - // is destroyed. - string16 name; - string16 message; - if (group) { - name = group->GetGroupName(); - message = l10n_util::GetStringFUTF16(message_id, name); - } else { - message = l10n_util::GetStringUTF16(message_id); - } - - BlockedPlugin* blocked_plugin = - new BlockedPlugin(render_view, - frame, - plugin, - params, - render_view->GetWebkitPreferences(), - resource_id, - name, - message, - is_blocked_for_prerendering, - allow_loading); - return blocked_plugin->plugin(); -} - bool ChromeContentRendererClient::HasErrorPage(int http_status_code, std::string* error_domain) { // Use an internal error page, if we have one for the status code. diff --git a/chrome/renderer/chrome_content_renderer_client.h b/chrome/renderer/chrome_content_renderer_client.h index 26c9605..ca85a81 100644 --- a/chrome/renderer/chrome_content_renderer_client.h +++ b/chrome/renderer/chrome_content_renderer_client.h @@ -116,17 +116,6 @@ class ChromeContentRendererClient : public content::ContentRendererClient { WebKit::WebFrame* frame, const WebKit::WebPluginParams& params); - WebKit::WebPlugin* CreatePluginPlaceholder( - content::RenderView* render_view, - WebKit::WebFrame* frame, - const webkit::WebPluginInfo& plugin, - const WebKit::WebPluginParams& params, - const webkit::npapi::PluginGroup* group, - int resource_id, - int message_id, - bool is_blocked_for_prerendering, - bool allow_loading); - // Returns the extension for the given URL. Excludes extension objects for // bookmark apps, which do not use the app process model. const Extension* GetNonBookmarkAppExtension(const ExtensionSet* extensions, diff --git a/chrome/renderer/custom_menu_commands.h b/chrome/renderer/custom_menu_commands.h new file mode 100644 index 0000000..e8bf53d --- /dev/null +++ b/chrome/renderer/custom_menu_commands.h @@ -0,0 +1,18 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_RENDERER_CUSTOM_MENU_COMMANDS_H_ +#define CHROME_RENDERER_CUSTOM_MENU_COMMANDS_H_ +#pragma once + +namespace chrome { + +enum MenuCommands { + MENU_COMMAND_PLUGIN_RUN = 1, + MENU_COMMAND_PLUGIN_HIDE = 2, +}; + +} // namespace chrome + +#endif // CHROME_RENDERER_CUSTOM_MENU_COMMANDS_H_ diff --git a/chrome/renderer/blocked_plugin.cc b/chrome/renderer/plugins/blocked_plugin.cc index 4db472a..806e711 100644 --- a/chrome/renderer/blocked_plugin.cc +++ b/chrome/renderer/plugins/blocked_plugin.cc @@ -2,113 +2,105 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/renderer/blocked_plugin.h" +#include "chrome/renderer/plugins/blocked_plugin.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/plugin_uma.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/WebData.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/WebPoint.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebRegularExpression.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebTextCaseSensitivity.h" #include "third_party/WebKit/Source/WebKit/chromium/public/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/npapi/webview_plugin.h" +#include "webkit/plugins/webview_plugin.h" using WebKit::WebContextMenuData; -using WebKit::WebElement; using WebKit::WebFrame; using WebKit::WebMenuItemInfo; -using WebKit::WebNode; using WebKit::WebPlugin; -using WebKit::WebPluginContainer; using WebKit::WebPluginParams; using WebKit::WebPoint; -using WebKit::WebRegularExpression; using WebKit::WebString; using WebKit::WebURLRequest; using WebKit::WebVector; using content::RenderThread; +using webkit::WebViewPlugin; -static const char* const kBlockedPluginDataURL = "chrome://blockedplugindata/"; -// TODO(cevans) - move these to a shared header file so that there are no -// collisions in the longer term. Currently, blocked_plugin.cc is the only -// user of custom menu commands (extension menu items have their own range). -static const unsigned kMenuActionLoad = 1; -static const unsigned kMenuActionRemove = 2; +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); -static const BlockedPlugin* g_last_active_menu; + 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 webkit::WebPluginInfo& info, const WebPluginParams& params, - const WebPreferences& preferences, - int template_id, + const std::string& html_data, + const webkit::WebPluginInfo& info, const string16& name, - const string16& message, bool is_blocked_for_prerendering, bool allow_loading) - : content::RenderViewObserver(render_view), - frame_(frame), + : PluginPlaceholder(render_view, frame, params, html_data), plugin_info_(info), - plugin_params_(params), name_(name), is_blocked_for_prerendering_(is_blocked_for_prerendering), hidden_(false), allow_loading_(allow_loading) { - const base::StringPiece template_html( - ResourceBundle::GetSharedInstance().GetRawDataResource(template_id)); - - DCHECK(!template_html.empty()) << "unable to load template. ID: " - << template_id; - - DictionaryValue values; - values.SetString("message", message); - values.SetString("name", name_); - values.SetString("hide", l10n_util::GetStringUTF8(IDS_PLUGIN_HIDE)); - - // "t" is the id of the templates root node. - std::string html_data = jstemplate_builder::GetI18nTemplateHtml( - template_html, &values); - - plugin_ = webkit::npapi::WebViewPlugin::Create(this, - preferences, - html_data, - GURL(kBlockedPluginDataURL)); } BlockedPlugin::~BlockedPlugin() { } void BlockedPlugin::BindWebFrame(WebFrame* frame) { - BindToJavascript(frame, "plugin"); + PluginPlaceholder::BindWebFrame(frame); BindMethod("load", &BlockedPlugin::LoadCallback); BindMethod("hide", &BlockedPlugin::HideCallback); BindMethod("openURL", &BlockedPlugin::OpenUrlCallback); } -void BlockedPlugin::WillDestroyPlugin() { - delete this; -} - void BlockedPlugin::ShowContextMenu(const WebKit::WebMouseEvent& event) { WebContextMenuData menu_data; @@ -129,7 +121,7 @@ void BlockedPlugin::ShowContextMenu(const WebKit::WebMouseEvent& event) { } WebMenuItemInfo run_item; - run_item.action = kMenuActionLoad; + 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( @@ -139,7 +131,7 @@ void BlockedPlugin::ShowContextMenu(const WebKit::WebMouseEvent& event) { custom_items[i++] = run_item; WebMenuItemInfo hide_item; - hide_item.action = kMenuActionRemove; + 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()); @@ -169,12 +161,19 @@ bool BlockedPlugin::OnMessageReceived(const IPC::Message& message) { void BlockedPlugin::ContextMenuAction(unsigned id) { if (g_last_active_menu != this) return; - if (id == kMenuActionLoad) { - RenderThread::Get()->RecordUserMetrics("Plugin_Load_Menu"); - LoadPlugin(); - } else if (id == kMenuActionRemove) { - RenderThread::Get()->RecordUserMetrics("Plugin_Hide_Menu"); - HidePlugin(); + 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(); } } @@ -192,28 +191,13 @@ void BlockedPlugin::OnSetIsPrerendering(bool is_prerendering) { } void BlockedPlugin::LoadPlugin() { - CHECK(plugin_); // 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; - WebPluginContainer* container = plugin_->container(); - WebPlugin* new_plugin = - render_view()->CreatePlugin(frame_, plugin_info_, plugin_params_); - if (new_plugin && new_plugin->initialize(container)) { - plugin_->RestoreTitleText(); - container->setPlugin(new_plugin); - container->invalidate(); - container->reportGeometry(); - plugin_->ReplayReceivedData(new_plugin); - plugin_->destroy(); - } else { - MissingPluginReporter::GetInstance()->ReportPluginMissing( - plugin_params_.mimeType.utf8(), - plugin_params_.url); - } + LoadPluginInternal(plugin_info_); } void BlockedPlugin::LoadCallback(const CppArgumentList& args, @@ -244,56 +228,10 @@ void BlockedPlugin::OpenUrlCallback(const CppArgumentList& args, request.initialize(); request.setURL(url); render_view()->LoadURLExternally( - frame_, request, WebKit::WebNavigationPolicyNewForegroundTab); + frame(), request, WebKit::WebNavigationPolicyNewForegroundTab); } void BlockedPlugin::HidePlugin() { - CHECK(plugin_); hidden_ = true; - WebPluginContainer* container = plugin_->container(); - WebElement element = container->element(); - element.setAttribute("style", "display: none;"); - // If we have a width and height, search for a parent (often <div>) with the - // same dimensions. If we find such a parent, hide that as well. - // This makes much more uncovered page content usable (including clickable) - // as opposed to merely visible. - // TODO(cevans) -- it's a foul heurisitc but we're going to tolerate it for - // now for these reasons: - // 1) Makes the user experience better. - // 2) Foulness is encapsulated within this single function. - // 3) Confidence in no fasle positives. - // 4) Seems to have a good / low false negative rate at this time. - if (element.hasAttribute("width") && element.hasAttribute("height")) { - std::string width_str("width:[\\s]*"); - width_str += element.getAttribute("width").utf8().data(); - if (EndsWith(width_str, "px", false)) { - width_str = width_str.substr(0, width_str.length() - 2); - } - TrimWhitespace(width_str, TRIM_TRAILING, &width_str); - width_str += "[\\s]*px"; - WebRegularExpression width_regex(WebString::fromUTF8(width_str.c_str()), - WebKit::WebTextCaseSensitive); - std::string height_str("height:[\\s]*"); - height_str += element.getAttribute("height").utf8().data(); - if (EndsWith(height_str, "px", false)) { - height_str = height_str.substr(0, height_str.length() - 2); - } - TrimWhitespace(height_str, TRIM_TRAILING, &height_str); - height_str += "[\\s]*px"; - WebRegularExpression height_regex(WebString::fromUTF8(height_str.c_str()), - WebKit::WebTextCaseSensitive); - WebNode parent = element; - while (!parent.parentNode().isNull()) { - parent = parent.parentNode(); - if (!parent.isElementNode()) - continue; - element = parent.toConst<WebElement>(); - if (element.hasAttribute("style")) { - WebString style_str = element.getAttribute("style"); - if (width_regex.match(style_str) >= 0 && - height_regex.match(style_str) >= 0) - element.setAttribute("style", "display: none;"); - } - } - } + HidePluginInternal(); } diff --git a/chrome/renderer/blocked_plugin.h b/chrome/renderer/plugins/blocked_plugin.h index abff76d..597b5e7 100644 --- a/chrome/renderer/blocked_plugin.h +++ b/chrome/renderer/plugins/blocked_plugin.h @@ -2,41 +2,47 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_RENDERER_BLOCKED_PLUGIN_H_ -#define CHROME_RENDERER_BLOCKED_PLUGIN_H_ +#ifndef CHROME_RENDERER_PLUGINS_BLOCKED_PLUGIN_H_ +#define CHROME_RENDERER_PLUGINS_BLOCKED_PLUGIN_H_ #pragma once -#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/npapi/webview_plugin.h" +#include "chrome/renderer/plugins/plugin_placeholder.h" #include "webkit/plugins/webplugininfo.h" -class BlockedPlugin : public content::RenderViewObserver, - public CppBoundClass, - public webkit::npapi::WebViewPlugin::Delegate { +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::WebPluginInfo& info, const WebKit::WebPluginParams& params, - const WebPreferences& settings, - int template_id, + const std::string& html_data, + const webkit::WebPluginInfo& info, const string16& name, - const string16& message, bool is_blocked_for_prerendering, bool allow_loading); - - webkit::npapi::WebViewPlugin* plugin() { return plugin_; } + virtual ~BlockedPlugin(); // WebViewPlugin::Delegate methods: virtual void BindWebFrame(WebKit::WebFrame* frame) OVERRIDE; - virtual void WillDestroyPlugin() OVERRIDE; virtual void ShowContextMenu(const WebKit::WebMouseEvent&) OVERRIDE; - private: - virtual ~BlockedPlugin(); - // RenderViewObserver methods: virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; virtual void ContextMenuAction(unsigned id) OVERRIDE; @@ -63,10 +69,7 @@ class BlockedPlugin : public content::RenderViewObserver, // Hide the blocked plugin. void HidePlugin(); - WebKit::WebFrame* frame_; webkit::WebPluginInfo plugin_info_; - WebKit::WebPluginParams plugin_params_; - webkit::npapi::WebViewPlugin* plugin_; // The name of the plugin that was blocked. string16 name_; // True iff the plugin was blocked because the page was being prerendered. @@ -76,4 +79,4 @@ class BlockedPlugin : public content::RenderViewObserver, bool allow_loading_; }; -#endif // CHROME_RENDERER_BLOCKED_PLUGIN_H_ +#endif // CHROME_RENDERER_PLUGINS_BLOCKED_PLUGIN_H_ diff --git a/chrome/renderer/plugins/missing_plugin.cc b/chrome/renderer/plugins/missing_plugin.cc new file mode 100644 index 0000000..9773414 --- /dev/null +++ b/chrome/renderer/plugins/missing_plugin.cc @@ -0,0 +1,124 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/renderer/plugins/missing_plugin.h" + +#include "base/string_piece.h" +#include "base/string_util.h" +#include "base/values.h" +#include "chrome/common/jstemplate_builder.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 "grit/renderer_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/WebPoint.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebVector.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::WebString; +using WebKit::WebVector; +using content::RenderThread; +using webkit::WebViewPlugin; + +namespace { +const MissingPlugin* g_last_active_menu = NULL; +} + +// static +WebViewPlugin* MissingPlugin::Create(content::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_NOT_FOUND)); + + // "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(content::RenderView* render_view, + WebFrame* frame, + const WebPluginParams& params, + const std::string& html_data) + : PluginPlaceholder(render_view, frame, params, html_data), + mime_type_(params.mimeType) { +} + +MissingPlugin::~MissingPlugin() { +} + +void MissingPlugin::BindWebFrame(WebFrame* frame) { + PluginPlaceholder::BindWebFrame(frame); + BindMethod("hide", &MissingPlugin::HideCallback); +} + +void MissingPlugin::HideCallback(const CppArgumentList& args, + CppVariant* result) { + RenderThread::Get()->RecordUserMetrics("MissingPlugin_Hide_Click"); + HidePluginInternal(); +} + +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 = mime_type_; + 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; +} + +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 new file mode 100644 index 0000000..7b3351f --- /dev/null +++ b/chrome/renderer/plugins/missing_plugin.h @@ -0,0 +1,41 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_RENDERER_PLUGINS_MISSING_PLUGIN_H_ +#define CHROME_RENDERER_PLUGINS_MISSING_PLUGIN_H_ +#pragma once + +#include "chrome/renderer/plugins/plugin_placeholder.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h" + +class MissingPlugin : public PluginPlaceholder { + 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); + + private: + MissingPlugin(content::RenderView* render_view, + WebKit::WebFrame* frame, + const WebKit::WebPluginParams& params, + const std::string& html_data); + virtual ~MissingPlugin(); + + // WebViewPlugin::Delegate methods: + virtual void BindWebFrame(WebKit::WebFrame* frame) OVERRIDE; + virtual void ShowContextMenu(const WebKit::WebMouseEvent&) OVERRIDE; + + // content::RenderViewObserver methods: + virtual void ContextMenuAction(unsigned id) OVERRIDE; + + void HideCallback(const CppArgumentList& args, CppVariant* result); + + WebKit::WebString mime_type_; + + 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 new file mode 100644 index 0000000..4bc97a6 --- /dev/null +++ b/chrome/renderer/plugins/plugin_placeholder.cc @@ -0,0 +1,126 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/renderer/plugins/plugin_placeholder.h" + +#include "base/string_util.h" +#include "chrome/renderer/plugins/plugin_uma.h" +#include "content/public/renderer/render_view.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebData.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/WebPluginContainer.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebRegularExpression.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebTextCaseSensitivity.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" + +using WebKit::WebElement; +using WebKit::WebFrame; +using WebKit::WebMouseEvent; +using WebKit::WebNode; +using WebKit::WebPlugin; +using WebKit::WebPluginContainer; +using WebKit::WebPluginParams; +using WebKit::WebRegularExpression; +using WebKit::WebString; +using webkit::WebPluginInfo; +using webkit::WebViewPlugin; + +static const char* const kPluginPlaceholderDataURL = + "chrome://pluginplaceholderdata/"; + +PluginPlaceholder::PluginPlaceholder(content::RenderView* render_view, + WebFrame* frame, + const WebPluginParams& params, + const std::string& html_data) + : content::RenderViewObserver(render_view), + frame_(frame), + plugin_params_(params), + plugin_(WebViewPlugin::Create( + this, render_view->GetWebkitPreferences(), html_data, + GURL(kPluginPlaceholderDataURL))) { +} + +PluginPlaceholder::~PluginPlaceholder() { +} + +void PluginPlaceholder::BindWebFrame(WebFrame* frame) { + BindToJavascript(frame, "plugin"); +} + +void PluginPlaceholder::LoadPluginInternal(const WebPluginInfo& plugin_info) { + CHECK(plugin_); + WebPluginContainer* container = plugin_->container(); + WebPlugin* new_plugin = + render_view()->CreatePlugin(frame_, plugin_info, plugin_params_); + if (new_plugin && new_plugin->initialize(container)) { + plugin_->RestoreTitleText(); + container->setPlugin(new_plugin); + container->invalidate(); + container->reportGeometry(); + plugin_->ReplayReceivedData(new_plugin); + plugin_->destroy(); + } else { + MissingPluginReporter::GetInstance()->ReportPluginMissing( + plugin_params_.mimeType.utf8(), + plugin_params_.url); + } +} + +void PluginPlaceholder::HidePluginInternal() { + WebPluginContainer* container = plugin_->container(); + WebElement element = container->element(); + element.setAttribute("style", "display: none;"); + // If we have a width and height, search for a parent (often <div>) with the + // same dimensions. If we find such a parent, hide that as well. + // This makes much more uncovered page content usable (including clickable) + // as opposed to merely visible. + // TODO(cevans) -- it's a foul heurisitc but we're going to tolerate it for + // now for these reasons: + // 1) Makes the user experience better. + // 2) Foulness is encapsulated within this single function. + // 3) Confidence in no fasle positives. + // 4) Seems to have a good / low false negative rate at this time. + if (element.hasAttribute("width") && element.hasAttribute("height")) { + std::string width_str("width:[\\s]*"); + width_str += element.getAttribute("width").utf8().data(); + if (EndsWith(width_str, "px", false)) { + width_str = width_str.substr(0, width_str.length() - 2); + } + TrimWhitespace(width_str, TRIM_TRAILING, &width_str); + width_str += "[\\s]*px"; + WebRegularExpression width_regex(WebString::fromUTF8(width_str.c_str()), + WebKit::WebTextCaseSensitive); + std::string height_str("height:[\\s]*"); + height_str += element.getAttribute("height").utf8().data(); + if (EndsWith(height_str, "px", false)) { + height_str = height_str.substr(0, height_str.length() - 2); + } + TrimWhitespace(height_str, TRIM_TRAILING, &height_str); + height_str += "[\\s]*px"; + WebRegularExpression height_regex(WebString::fromUTF8(height_str.c_str()), + WebKit::WebTextCaseSensitive); + WebNode parent = element; + while (!parent.parentNode().isNull()) { + parent = parent.parentNode(); + if (!parent.isElementNode()) + continue; + element = parent.toConst<WebElement>(); + if (element.hasAttribute("style")) { + WebString style_str = element.getAttribute("style"); + if (width_regex.match(style_str) >= 0 && + height_regex.match(style_str) >= 0) + element.setAttribute("style", "display: none;"); + } + } + } +} + +void PluginPlaceholder::WillDestroyPlugin() { + delete this; +} + +void PluginPlaceholder::ShowContextMenu(const WebMouseEvent& event) { +} diff --git a/chrome/renderer/plugins/plugin_placeholder.h b/chrome/renderer/plugins/plugin_placeholder.h new file mode 100644 index 0000000..009d300 --- /dev/null +++ b/chrome/renderer/plugins/plugin_placeholder.h @@ -0,0 +1,56 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_RENDERER_PLUGINS_PLUGIN_PLACEHOLDER_H_ +#define CHROME_RENDERER_PLUGINS_PLUGIN_PLACEHOLDER_H_ +#pragma once + +#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/webview_plugin.h" + +namespace webkit { +struct WebPluginInfo; +} + +// 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). +class PluginPlaceholder : public content::RenderViewObserver, + public CppBoundClass, + public webkit::WebViewPlugin::Delegate { + protected: + // |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_; } + + // Can be called by a subclass to replace this placeholder with an actual + // plugin from |plugin_info|. + void LoadPluginInternal(const webkit::WebPluginInfo& plugin_info); + + // 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; + + private: + WebKit::WebFrame* frame_; + WebKit::WebPluginParams plugin_params_; + webkit::WebViewPlugin* plugin_; + + DISALLOW_COPY_AND_ASSIGN(PluginPlaceholder); +}; + +#endif // CHROME_RENDERER_PLUGINS_PLUGIN_PLACEHOLDER_H_ diff --git a/chrome/renderer/plugin_uma.cc b/chrome/renderer/plugins/plugin_uma.cc index ad215b7..5f1bec1 100644 --- a/chrome/renderer/plugin_uma.cc +++ b/chrome/renderer/plugins/plugin_uma.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/renderer/plugin_uma.h" +#include "chrome/renderer/plugins/plugin_uma.h" #include <algorithm> #include <cstring> diff --git a/chrome/renderer/plugin_uma.h b/chrome/renderer/plugins/plugin_uma.h index 411a8ae..f1eb4cf 100644 --- a/chrome/renderer/plugin_uma.h +++ b/chrome/renderer/plugins/plugin_uma.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_RENDERER_PLUGIN_UMA_H_ -#define CHROME_RENDERER_PLUGIN_UMA_H_ +#ifndef CHROME_RENDERER_PLUGINS_PLUGIN_UMA_H_ +#define CHROME_RENDERER_PLUGINS_PLUGIN_UMA_H_ #include <string> @@ -66,5 +66,5 @@ class MissingPluginReporter { DISALLOW_COPY_AND_ASSIGN(MissingPluginReporter); }; -#endif // CHROME_RENDERER_PLUGIN_UMA_H_ +#endif // CHROME_RENDERER_PLUGINS_PLUGIN_UMA_H_ diff --git a/chrome/renderer/plugin_uma_unittest.cc b/chrome/renderer/plugins/plugin_uma_unittest.cc index c59d932..46e8099 100644 --- a/chrome/renderer/plugin_uma_unittest.cc +++ b/chrome/renderer/plugins/plugin_uma_unittest.cc @@ -5,7 +5,7 @@ #include <gmock/gmock.h> #include <gtest/gtest.h> -#include "chrome/renderer/plugin_uma.h" +#include "chrome/renderer/plugins/plugin_uma.h" using ::testing::_; |