diff options
21 files changed, 945 insertions, 1180 deletions
diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi index 4b394e5..586e3e4 100644 --- a/chrome/chrome_renderer.gypi +++ b/chrome/chrome_renderer.gypi @@ -15,7 +15,6 @@ 'chrome_resources.gyp:chrome_strings', '../components/components.gyp:autofill_content_renderer', '../components/components.gyp:startup_metric_utils', - '../components/components.gyp:plugins_renderer', '../components/components.gyp:translate_common', '../components/components.gyp:translate_language_detection', '../components/components.gyp:visitedlink_renderer', @@ -266,10 +265,12 @@ 'renderer/pepper/ppb_nacl_private_impl.h', 'renderer/pepper/ppb_pdf_impl.cc', 'renderer/pepper/ppb_pdf_impl.h', - 'renderer/plugins/chrome_plugin_placeholder.cc', - 'renderer/plugins/chrome_plugin_placeholder.h', + 'renderer/plugins/plugin_placeholder.cc', + 'renderer/plugins/plugin_placeholder.h', 'renderer/plugins/plugin_uma.cc', 'renderer/plugins/plugin_uma.h', + 'renderer/plugins/webview_plugin.cc', + 'renderer/plugins/webview_plugin.h', 'renderer/prerender/prerender_dispatcher.cc', 'renderer/prerender/prerender_dispatcher.h', 'renderer/prerender/prerender_extra_data.cc', @@ -432,6 +433,9 @@ 'renderer/extensions/tabs_custom_bindings.cc', 'renderer/extensions/tts_custom_bindings.cc', ], + 'defines': [ + 'ENABLE_MOBILE_YOUTUBE_PLUGIN', + ], 'conditions' : [ ['google_tv==1', { 'sources!' : [ diff --git a/chrome/renderer/DEPS b/chrome/renderer/DEPS index cc3dfff..4c70eea 100644 --- a/chrome/renderer/DEPS +++ b/chrome/renderer/DEPS @@ -1,7 +1,6 @@ include_rules = [ "+components/autofill/content/renderer", "+components/autofill/core/common", - "+components/plugins/renderer", "+components/translate/common", "+components/translate/language_detection", "+components/visitedlink/renderer", diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index 488082d..8672dcc 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc @@ -50,7 +50,7 @@ #include "chrome/renderer/pepper/ppb_nacl_private_impl.h" #include "chrome/renderer/pepper/ppb_pdf_impl.h" #include "chrome/renderer/playback_extension.h" -#include "chrome/renderer/plugins/chrome_plugin_placeholder.h" +#include "chrome/renderer/plugins/plugin_placeholder.h" #include "chrome/renderer/plugins/plugin_uma.h" #include "chrome/renderer/prerender/prerender_dispatcher.h" #include "chrome/renderer/prerender/prerender_helper.h" @@ -68,7 +68,6 @@ #include "components/autofill/content/renderer/password_autofill_agent.h" #include "components/autofill/content/renderer/password_generation_agent.h" #include "components/autofill/core/common/password_generation_util.h" -#include "components/plugins/renderer/mobile_youtube_plugin.h" #include "components/visitedlink/renderer/visitedlink_slave.h" #include "content/public/common/content_constants.h" #include "content/public/renderer/render_thread.h" @@ -470,8 +469,8 @@ bool ChromeContentRendererClient::OverrideCreatePlugin( WebPlugin* ChromeContentRendererClient::CreatePluginReplacement( content::RenderView* render_view, const base::FilePath& plugin_path) { - ChromePluginPlaceholder* placeholder = - ChromePluginPlaceholder::CreateErrorPlugin(render_view, plugin_path); + PluginPlaceholder* placeholder = + PluginPlaceholder::CreateErrorPlugin(render_view, plugin_path); return placeholder->plugin(); } @@ -506,29 +505,20 @@ WebPlugin* ChromeContentRendererClient::CreatePlugin( ChromeViewHostMsg_GetPluginInfo_Status::Value status_value = status.value; GURL url(original_params.url); std::string orig_mime_type = original_params.mimeType.utf8(); - ChromePluginPlaceholder* placeholder = NULL; + PluginPlaceholder* placeholder = NULL; // If the browser plugin is to be enabled, this should be handled by the // renderer, so the code won't reach here due to the early exit in // OverrideCreatePlugin. if (status_value == ChromeViewHostMsg_GetPluginInfo_Status::kNotFound || orig_mime_type == content::kBrowserPluginMimeType) { -#if defined(OS_ANDROID) - if (plugins::MobileYouTubePlugin::IsYouTubeURL(url, orig_mime_type)) { - base::StringPiece template_html( - ResourceBundle::GetSharedInstance().GetRawDataResource( - IDR_MOBILE_YOUTUBE_PLUGIN_HTML)); - return (new plugins::MobileYouTubePlugin( - render_view, - frame, - original_params, - template_html, - GURL(ChromePluginPlaceholder::kPluginPlaceholderDataURL))) - ->plugin(); - } +#if defined(ENABLE_MOBILE_YOUTUBE_PLUGIN) + if (PluginPlaceholder::IsYouTubeURL(url, orig_mime_type)) + return PluginPlaceholder::CreateMobileYoutubePlugin(render_view, frame, + original_params)->plugin(); #endif PluginUMAReporter::GetInstance()->ReportPluginMissing(orig_mime_type, url); - placeholder = ChromePluginPlaceholder::CreateMissingPlugin( + placeholder = PluginPlaceholder::CreateMissingPlugin( render_view, frame, original_params); } else { // TODO(bauerb): This should be in content/. @@ -642,13 +632,8 @@ WebPlugin* ChromeContentRendererClient::CreatePlugin( frame->addMessageToConsole( WebConsoleMessage(WebConsoleMessage::LevelError, error_message)); - placeholder = ChromePluginPlaceholder::CreateBlockedPlugin( - render_view, - frame, - params, - plugin, - identifier, - group_name, + placeholder = PluginPlaceholder::CreateBlockedPlugin( + render_view, frame, params, plugin, identifier, group_name, IDR_BLOCKED_PLUGIN_HTML, #if defined(OS_CHROMEOS) l10n_util::GetStringUTF16(IDS_NACL_PLUGIN_BLOCKED)); @@ -664,13 +649,8 @@ WebPlugin* ChromeContentRendererClient::CreatePlugin( // ChromeContentRendererClient::CreatePlugin instead, to // reduce the chance of future regressions. if (prerender::PrerenderHelper::IsPrerendering(render_view)) { - placeholder = ChromePluginPlaceholder::CreateBlockedPlugin( - render_view, - frame, - params, - plugin, - identifier, - group_name, + placeholder = PluginPlaceholder::CreateBlockedPlugin( + render_view, frame, params, plugin, identifier, group_name, IDR_CLICK_TO_PLAY_PLUGIN_HTML, l10n_util::GetStringFUTF16(IDS_PLUGIN_LOAD, group_name)); placeholder->set_blocked_for_prerendering(true); @@ -682,13 +662,8 @@ WebPlugin* ChromeContentRendererClient::CreatePlugin( } case ChromeViewHostMsg_GetPluginInfo_Status::kNPAPINotSupported: { RenderThread::Get()->RecordUserMetrics("Plugin_NPAPINotSupported"); - placeholder = ChromePluginPlaceholder::CreateBlockedPlugin( - render_view, - frame, - params, - plugin, - identifier, - group_name, + placeholder = PluginPlaceholder::CreateBlockedPlugin( + render_view, frame, params, plugin, identifier, group_name, IDR_BLOCKED_PLUGIN_HTML, l10n_util::GetStringUTF16(IDS_PLUGIN_NOT_SUPPORTED_METRO)); render_view->Send(new ChromeViewHostMsg_NPAPINotSupported( @@ -698,26 +673,16 @@ WebPlugin* ChromeContentRendererClient::CreatePlugin( case ChromeViewHostMsg_GetPluginInfo_Status::kDisabled: { PluginUMAReporter::GetInstance()->ReportPluginDisabled(orig_mime_type, url); - placeholder = ChromePluginPlaceholder::CreateBlockedPlugin( - render_view, - frame, - params, - plugin, - identifier, - group_name, + placeholder = PluginPlaceholder::CreateBlockedPlugin( + render_view, frame, params, plugin, identifier, group_name, IDR_DISABLED_PLUGIN_HTML, l10n_util::GetStringFUTF16(IDS_PLUGIN_DISABLED, group_name)); break; } case ChromeViewHostMsg_GetPluginInfo_Status::kOutdatedBlocked: { #if defined(ENABLE_PLUGIN_INSTALLATION) - placeholder = ChromePluginPlaceholder::CreateBlockedPlugin( - render_view, - frame, - params, - plugin, - identifier, - group_name, + placeholder = PluginPlaceholder::CreateBlockedPlugin( + render_view, frame, params, plugin, identifier, group_name, IDR_BLOCKED_PLUGIN_HTML, l10n_util::GetStringFUTF16(IDS_PLUGIN_OUTDATED, group_name)); placeholder->set_allow_loading(true); @@ -730,25 +695,15 @@ WebPlugin* ChromeContentRendererClient::CreatePlugin( break; } case ChromeViewHostMsg_GetPluginInfo_Status::kOutdatedDisallowed: { - placeholder = ChromePluginPlaceholder::CreateBlockedPlugin( - render_view, - frame, - params, - plugin, - identifier, - group_name, + placeholder = PluginPlaceholder::CreateBlockedPlugin( + render_view, frame, params, plugin, identifier, group_name, IDR_BLOCKED_PLUGIN_HTML, l10n_util::GetStringFUTF16(IDS_PLUGIN_OUTDATED, group_name)); break; } case ChromeViewHostMsg_GetPluginInfo_Status::kUnauthorized: { - placeholder = ChromePluginPlaceholder::CreateBlockedPlugin( - render_view, - frame, - params, - plugin, - identifier, - group_name, + placeholder = PluginPlaceholder::CreateBlockedPlugin( + render_view, frame, params, plugin, identifier, group_name, IDR_BLOCKED_PLUGIN_HTML, l10n_util::GetStringFUTF16(IDS_PLUGIN_NOT_AUTHORIZED, group_name)); placeholder->set_allow_loading(true); @@ -759,13 +714,8 @@ WebPlugin* ChromeContentRendererClient::CreatePlugin( break; } case ChromeViewHostMsg_GetPluginInfo_Status::kClickToPlay: { - placeholder = ChromePluginPlaceholder::CreateBlockedPlugin( - render_view, - frame, - params, - plugin, - identifier, - group_name, + placeholder = PluginPlaceholder::CreateBlockedPlugin( + render_view, frame, params, plugin, identifier, group_name, IDR_CLICK_TO_PLAY_PLUGIN_HTML, l10n_util::GetStringFUTF16(IDS_PLUGIN_LOAD, group_name)); placeholder->set_allow_loading(true); @@ -774,13 +724,8 @@ WebPlugin* ChromeContentRendererClient::CreatePlugin( break; } case ChromeViewHostMsg_GetPluginInfo_Status::kBlocked: { - placeholder = ChromePluginPlaceholder::CreateBlockedPlugin( - render_view, - frame, - params, - plugin, - identifier, - group_name, + placeholder = PluginPlaceholder::CreateBlockedPlugin( + render_view, frame, params, plugin, identifier, group_name, IDR_BLOCKED_PLUGIN_HTML, l10n_util::GetStringFUTF16(IDS_PLUGIN_BLOCKED, group_name)); placeholder->set_allow_loading(true); diff --git a/chrome/renderer/plugins/chrome_plugin_placeholder.cc b/chrome/renderer/plugins/chrome_plugin_placeholder.cc deleted file mode 100644 index 0b2e106..0000000 --- a/chrome/renderer/plugins/chrome_plugin_placeholder.cc +++ /dev/null @@ -1,359 +0,0 @@ -// Copyright 2013 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/chrome_plugin_placeholder.h" - -#include "base/strings/utf_string_conversions.h" -#include "base/values.h" -#include "chrome/common/prerender_messages.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/common/context_menu_params.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 "grit/webkit_strings.h" -#include "third_party/WebKit/public/web/WebDocument.h" -#include "third_party/WebKit/public/web/WebFrame.h" -#include "third_party/WebKit/public/web/WebInputEvent.h" -#include "third_party/WebKit/public/web/WebScriptSource.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/webui/jstemplate_builder.h" - -using content::RenderThread; -using content::RenderView; -using WebKit::WebDocument; -using WebKit::WebElement; -using WebKit::WebFrame; -using WebKit::WebMouseEvent; -using WebKit::WebNode; -using WebKit::WebPlugin; -using WebKit::WebPluginContainer; -using WebKit::WebPluginParams; -using webkit_glue::CppArgumentList; -using webkit_glue::CppVariant; - -namespace { -const plugins::PluginPlaceholder* g_last_active_menu = NULL; -} // namespace - -const char ChromePluginPlaceholder::kPluginPlaceholderDataURL[] = - "chrome://pluginplaceholderdata/"; - -ChromePluginPlaceholder::ChromePluginPlaceholder( - content::RenderView* render_view, - WebKit::WebFrame* frame, - const WebKit::WebPluginParams& params, - const std::string& html_data, - const string16& title) - : plugins::PluginPlaceholder(render_view, - frame, - params, - html_data, - GURL(kPluginPlaceholderDataURL)), - status_(new ChromeViewHostMsg_GetPluginInfo_Status), - title_(title), -#if defined(ENABLE_PLUGIN_INSTALLATION) - placeholder_routing_id_(MSG_ROUTING_NONE), -#endif - has_host_(false), - context_menu_request_id_(0) { - RenderThread::Get()->AddObserver(this); -} - -ChromePluginPlaceholder::~ChromePluginPlaceholder() { -#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 - RenderThread::Get()->RemoveObserver(this); - if (context_menu_request_id_) - render_view()->CancelContextMenu(context_menu_request_id_); -} - -// static -ChromePluginPlaceholder* ChromePluginPlaceholder::CreateMissingPlugin( - RenderView* render_view, - WebFrame* frame, - const WebPluginParams& params) { - const base::StringPiece template_html( - ResourceBundle::GetSharedInstance().GetRawDataResource( - IDR_BLOCKED_PLUGIN_HTML)); - - base::DictionaryValue values; -#if defined(ENABLE_PLUGIN_INSTALLATION) - values.SetString("message", l10n_util::GetStringUTF8(IDS_PLUGIN_SEARCHING)); -#else - values.SetString("message", - l10n_util::GetStringUTF8(IDS_PLUGIN_NOT_SUPPORTED)); -#endif - - std::string html_data = webui::GetI18nTemplateHtml(template_html, &values); - - // |missing_plugin| will destroy itself when its WebViewPlugin is going away. - ChromePluginPlaceholder* missing_plugin = new ChromePluginPlaceholder( - 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())); -#endif - return missing_plugin; -} - -// static -ChromePluginPlaceholder* ChromePluginPlaceholder::CreateErrorPlugin( - RenderView* render_view, - const base::FilePath& file_path) { - base::DictionaryValue values; - values.SetString("message", - l10n_util::GetStringUTF8(IDS_PLUGIN_INITIALIZATION_ERROR)); - - const base::StringPiece template_html( - ResourceBundle::GetSharedInstance().GetRawDataResource( - IDR_BLOCKED_PLUGIN_HTML)); - std::string html_data = webui::GetI18nTemplateHtml(template_html, &values); - - WebPluginParams params; - // |missing_plugin| will destroy itself when its WebViewPlugin is going away. - ChromePluginPlaceholder* plugin = new ChromePluginPlaceholder( - render_view, NULL, params, html_data, params.mimeType); - - RenderThread::Get()->Send(new ChromeViewHostMsg_CouldNotLoadPlugin( - plugin->routing_id(), file_path)); - return plugin; -} - -// static -ChromePluginPlaceholder* ChromePluginPlaceholder::CreateBlockedPlugin( - RenderView* render_view, - WebFrame* frame, - const WebPluginParams& params, - const content::WebPluginInfo& plugin, - const std::string& identifier, - const string16& name, - int template_id, - const string16& message) { - base::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 = webui::GetI18nTemplateHtml(template_html, &values); - - // |blocked_plugin| will destroy itself when its WebViewPlugin is going away. - ChromePluginPlaceholder* blocked_plugin = - new ChromePluginPlaceholder(render_view, frame, params, html_data, name); - blocked_plugin->SetPluginInfo(plugin); - blocked_plugin->SetIdentifier(identifier); - return blocked_plugin; -} - -void ChromePluginPlaceholder::SetStatus( - const ChromeViewHostMsg_GetPluginInfo_Status& status) { - status_->value = status.value; -} - -#if defined(ENABLE_PLUGIN_INSTALLATION) -int32 ChromePluginPlaceholder::CreateRoutingId() { - placeholder_routing_id_ = RenderThread::Get()->GenerateRoutingID(); - RenderThread::Get()->AddRoute(placeholder_routing_id_, this); - return placeholder_routing_id_; -} -#endif - -bool ChromePluginPlaceholder::OnMessageReceived(const IPC::Message& message) { -#if defined(ENABLE_PLUGIN_INSTALLATION) - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(ChromePluginPlaceholder, 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_HANDLER(ChromeViewMsg_CancelledDownloadingPlugin, - OnCancelledDownloadingPlugin) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - - if (handled) - return true; -#endif - - // We don't swallow these messages because multiple blocked plugins have an - // interest in them. - IPC_BEGIN_MESSAGE_MAP(ChromePluginPlaceholder, message) - IPC_MESSAGE_HANDLER(ChromeViewMsg_LoadBlockedPlugins, OnLoadBlockedPlugins) - IPC_MESSAGE_HANDLER(PrerenderMsg_SetIsPrerendering, OnSetIsPrerendering) - IPC_END_MESSAGE_MAP() - - return false; -} - -void ChromePluginPlaceholder::OnLoadBlockedPlugins( - const std::string& identifier) { - plugins::PluginPlaceholder::OnLoadBlockedPlugins(identifier); -} - -void ChromePluginPlaceholder::OpenAboutPluginsCallback( - const CppArgumentList& args, - CppVariant* result) { - RenderThread::Get()->Send( - new ChromeViewHostMsg_OpenAboutPlugins(routing_id())); -} - -void ChromePluginPlaceholder::OnSetIsPrerendering(bool is_prerendering) { - plugins::PluginPlaceholder::OnSetIsPrerendering(is_prerendering); -} - -#if defined(ENABLE_PLUGIN_INSTALLATION) -void ChromePluginPlaceholder::OnDidNotFindMissingPlugin() { - SetMessage(l10n_util::GetStringUTF16(IDS_PLUGIN_NOT_FOUND)); -} - -void ChromePluginPlaceholder::OnFoundMissingPlugin( - const string16& plugin_name) { - if (status_->value == ChromeViewHostMsg_GetPluginInfo_Status::kNotFound) - SetMessage(l10n_util::GetStringFUTF16(IDS_PLUGIN_FOUND, plugin_name)); - has_host_ = true; - plugin_name_ = plugin_name; -} - -void ChromePluginPlaceholder::OnStartedDownloadingPlugin() { - SetMessage(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOADING, plugin_name_)); -} - -void ChromePluginPlaceholder::OnFinishedDownloadingPlugin() { - bool is_installing = - status_->value == ChromeViewHostMsg_GetPluginInfo_Status::kNotFound; - SetMessage(l10n_util::GetStringFUTF16( - is_installing ? IDS_PLUGIN_INSTALLING : IDS_PLUGIN_UPDATING, - plugin_name_)); -} - -void ChromePluginPlaceholder::OnErrorDownloadingPlugin( - const std::string& error) { - SetMessage(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOAD_ERROR, - UTF8ToUTF16(error))); -} - -void ChromePluginPlaceholder::OnCancelledDownloadingPlugin() { - SetMessage( - l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOAD_CANCELLED, plugin_name_)); -} -#endif // defined(ENABLE_PLUGIN_INSTALLATION) - -void ChromePluginPlaceholder::PluginListChanged() { - if (!GetFrame()) - return; - WebDocument document = GetFrame()->top()->document(); - if (document.isNull()) - return; - - ChromeViewHostMsg_GetPluginInfo_Output output; - std::string mime_type(GetPluginParams().mimeType.utf8()); - render_view()->Send( - new ChromeViewHostMsg_GetPluginInfo(routing_id(), - GURL(GetPluginParams().url), - document.url(), - mime_type, - &output)); - if (output.status.value == status_->value) - return; - WebPlugin* new_plugin = chrome::ChromeContentRendererClient::CreatePlugin( - render_view(), GetFrame(), GetPluginParams(), output); - ReplacePlugin(new_plugin); - if (!new_plugin) { - PluginUMAReporter::GetInstance()->ReportPluginMissing( - GetPluginParams().mimeType.utf8(), GURL(GetPluginParams().url)); - } -} - -void ChromePluginPlaceholder::OnMenuAction(int request_id, unsigned action) { - DCHECK_EQ(context_menu_request_id_, request_id); - if (g_last_active_menu != this) - return; - switch (action) { - 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 ChromePluginPlaceholder::OnMenuClosed(int request_id) { - DCHECK_EQ(context_menu_request_id_, request_id); - context_menu_request_id_ = 0; -} - -void ChromePluginPlaceholder::ShowContextMenu(const WebMouseEvent& event) { - if (context_menu_request_id_) - return; // Don't allow nested context menu requests. - - content::ContextMenuParams params; - - content::MenuItem name_item; - name_item.label = title_; - params.custom_items.push_back(name_item); - - content::MenuItem separator_item; - separator_item.type = content::MenuItem::SEPARATOR; - params.custom_items.push_back(separator_item); - - if (!GetPluginInfo().path.value().empty()) { - content::MenuItem run_item; - run_item.action = chrome::MENU_COMMAND_PLUGIN_RUN; - // Disable this menu item if the plugin is blocked by policy. - run_item.enabled = LoadingAllowed(); - run_item.label = l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_PLUGIN_RUN); - params.custom_items.push_back(run_item); - } - - content::MenuItem hide_item; - hide_item.action = chrome::MENU_COMMAND_PLUGIN_HIDE; - hide_item.enabled = true; - hide_item.label = l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_PLUGIN_HIDE); - params.custom_items.push_back(hide_item); - - params.x = event.windowX; - params.y = event.windowY; - - context_menu_request_id_ = render_view()->ShowContextMenu(this, params); - g_last_active_menu = this; -} - -void ChromePluginPlaceholder::BindWebFrame(WebKit::WebFrame* frame) { - plugins::PluginPlaceholder::BindWebFrame(frame); - BindCallback("openAboutPlugins", - base::Bind(&ChromePluginPlaceholder::OpenAboutPluginsCallback, - base::Unretained(this))); -} diff --git a/chrome/renderer/plugins/chrome_plugin_placeholder.h b/chrome/renderer/plugins/chrome_plugin_placeholder.h deleted file mode 100644 index fefab1b..0000000 --- a/chrome/renderer/plugins/chrome_plugin_placeholder.h +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright 2013 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_CHROME_PLUGIN_PLACEHOLDER_H_ -#define CHROME_RENDERER_PLUGINS_CHROME_PLUGIN_PLACEHOLDER_H_ - -#include "components/plugins/renderer/plugin_placeholder.h" - -struct ChromeViewHostMsg_GetPluginInfo_Status; - -class ChromePluginPlaceholder : public plugins::PluginPlaceholder, - public content::RenderProcessObserver, - public content::ContextMenuClient { - public: - static const char kPluginPlaceholderDataURL[]; - - static ChromePluginPlaceholder* CreateBlockedPlugin( - content::RenderView* render_view, - WebKit::WebFrame* frame, - const WebKit::WebPluginParams& params, - const content::WebPluginInfo& info, - const std::string& identifier, - const string16& name, - int resource_id, - const string16& message); - - // Creates a new WebViewPlugin with a MissingPlugin as a delegate. - static ChromePluginPlaceholder* CreateMissingPlugin( - content::RenderView* render_view, - WebKit::WebFrame* frame, - const WebKit::WebPluginParams& params); - - static ChromePluginPlaceholder* CreateErrorPlugin( - content::RenderView* render_view, - const base::FilePath& plugin_path); - - void SetStatus(const ChromeViewHostMsg_GetPluginInfo_Status& status); - -#if defined(ENABLE_PLUGIN_INSTALLATION) - int32 CreateRoutingId(); -#endif - - private: - ChromePluginPlaceholder(content::RenderView* render_view, - WebKit::WebFrame* frame, - const WebKit::WebPluginParams& params, - const std::string& html_data, - const string16& title); - virtual ~ChromePluginPlaceholder(); - - // WebViewPlugin::Delegate (via PluginPlaceholder) method - virtual void BindWebFrame(WebKit::WebFrame* frame) OVERRIDE; - - // content::RenderViewObserver (via PluginPlaceholder) override: - virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; - - // WebViewPlugin::Delegate (via PluginPlaceholder) methods: - virtual void ShowContextMenu(const WebKit::WebMouseEvent&) OVERRIDE; - - // content::RenderProcessObserver methods: - virtual void PluginListChanged() OVERRIDE; - - // content::ContextMenuClient methods: - virtual void OnMenuAction(int request_id, unsigned action) OVERRIDE; - virtual void OnMenuClosed(int request_id) OVERRIDE; - - // Javascript callback opens chrome://plugins in a new tab. - // Arguments are required by the caller, but not used. - void OpenAboutPluginsCallback(const webkit_glue::CppArgumentList& args, - webkit_glue::CppVariant* result); - - void OnLoadBlockedPlugins(const std::string& identifier); - void OnSetIsPrerendering(bool is_prerendering); -#if defined(ENABLE_PLUGIN_INSTALLATION) - void OnDidNotFindMissingPlugin(); - void OnFoundMissingPlugin(const string16& plugin_name); - void OnStartedDownloadingPlugin(); - void OnFinishedDownloadingPlugin(); - void OnErrorDownloadingPlugin(const std::string& error); - void OnCancelledDownloadingPlugin(); -#endif - - // 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_; - - string16 title_; - -#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 has_host_; - int context_menu_request_id_; // Nonzero when request pending. - string16 plugin_name_; - - DISALLOW_COPY_AND_ASSIGN(ChromePluginPlaceholder); -}; - -#endif // CHROME_RENDERER_PLUGINS_CHROME_PLUGIN_PLACEHOLDER_H_ diff --git a/chrome/renderer/plugins/plugin_placeholder.cc b/chrome/renderer/plugins/plugin_placeholder.cc new file mode 100644 index 0000000..0e58e72 --- /dev/null +++ b/chrome/renderer/plugins/plugin_placeholder.cc @@ -0,0 +1,626 @@ +// 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/plugin_placeholder.h" + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/json/string_escape.h" +#include "base/strings/string_piece.h" +#include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" +#include "base/values.h" +#include "chrome/common/prerender_messages.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/common/content_constants.h" +#include "content/public/common/context_menu_params.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 "grit/webkit_strings.h" +#include "third_party/WebKit/public/platform/WebData.h" +#include "third_party/WebKit/public/platform/WebPoint.h" +#include "third_party/WebKit/public/platform/WebURLRequest.h" +#include "third_party/WebKit/public/platform/WebVector.h" +#include "third_party/WebKit/public/web/WebContextMenuData.h" +#include "third_party/WebKit/public/web/WebDocument.h" +#include "third_party/WebKit/public/web/WebElement.h" +#include "third_party/WebKit/public/web/WebFrame.h" +#include "third_party/WebKit/public/web/WebInputEvent.h" +#include "third_party/WebKit/public/web/WebPluginContainer.h" +#include "third_party/WebKit/public/web/WebScriptSource.h" +#include "third_party/WebKit/public/web/WebView.h" +#include "third_party/re2/re2/re2.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/webui/jstemplate_builder.h" + +using content::RenderThread; +using content::RenderView; +using WebKit::WebContextMenuData; +using WebKit::WebDocument; +using WebKit::WebElement; +using WebKit::WebFrame; +using WebKit::WebMouseEvent; +using WebKit::WebNode; +using WebKit::WebPlugin; +using WebKit::WebPluginContainer; +using WebKit::WebPluginParams; +using WebKit::WebPoint; +using WebKit::WebScriptSource; +using WebKit::WebString; +using WebKit::WebURLRequest; +using WebKit::WebVector; +using webkit_glue::CppArgumentList; +using webkit_glue::CppVariant; + +const char* const kPluginPlaceholderDataURL = + "chrome://pluginplaceholderdata/"; + +#if defined(ENABLE_MOBILE_YOUTUBE_PLUGIN) +// Strings we used to parse the youtube plugin url. +const char* const kSlashVSlash = "/v/"; +const char* const kSlashESlash = "/e/"; +#endif + +namespace { +const PluginPlaceholder* g_last_active_menu = NULL; + +#if defined(ENABLE_MOBILE_YOUTUBE_PLUGIN) +// Helper function to get the youtube id from plugin params for old style +// embedded youtube video. +std::string GetYoutubeVideoId(const WebPluginParams& params) { + GURL url(params.url); + std::string video_id = url.path().substr(strlen(kSlashVSlash)); + + // Extract just the video id + size_t video_id_end = video_id.find('&'); + if (video_id_end != std::string::npos) + video_id = video_id.substr(0, video_id_end); + return video_id; +} +#endif +} // namespace + +// static +PluginPlaceholder* PluginPlaceholder::CreateMissingPlugin( + RenderView* render_view, + WebFrame* frame, + const WebPluginParams& params) { + const base::StringPiece template_html( + ResourceBundle::GetSharedInstance().GetRawDataResource( + IDR_BLOCKED_PLUGIN_HTML)); + + base::DictionaryValue values; +#if defined(ENABLE_PLUGIN_INSTALLATION) + values.SetString("message", l10n_util::GetStringUTF8(IDS_PLUGIN_SEARCHING)); +#else + values.SetString("message", + l10n_util::GetStringUTF8(IDS_PLUGIN_NOT_SUPPORTED)); +#endif + + std::string html_data = webui::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())); +#endif + return missing_plugin; +} + +PluginPlaceholder* PluginPlaceholder::CreateErrorPlugin( + RenderView* render_view, + const base::FilePath& file_path) { + base::DictionaryValue values; + values.SetString("message", + l10n_util::GetStringUTF8(IDS_PLUGIN_INITIALIZATION_ERROR)); + + const base::StringPiece template_html( + ResourceBundle::GetSharedInstance().GetRawDataResource( + IDR_BLOCKED_PLUGIN_HTML)); + std::string html_data = webui::GetI18nTemplateHtml(template_html, &values); + + WebPluginParams params; + // |missing_plugin| will destroy itself when its WebViewPlugin is going away. + PluginPlaceholder* plugin = new PluginPlaceholder( + render_view, NULL, params, html_data, params.mimeType); + + RenderThread::Get()->Send( + new ChromeViewHostMsg_CouldNotLoadPlugin(plugin->routing_id(), + file_path)); + return plugin; +} + +// static +PluginPlaceholder* PluginPlaceholder::CreateBlockedPlugin( + RenderView* render_view, + WebFrame* frame, + const WebPluginParams& params, + const content::WebPluginInfo& plugin, + const std::string& identifier, + const string16& name, + int template_id, + const string16& message) { + base::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 = webui::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; + blocked_plugin->identifier_ = identifier; + return blocked_plugin; +} + +#if defined(ENABLE_MOBILE_YOUTUBE_PLUGIN) +// static +PluginPlaceholder* PluginPlaceholder::CreateMobileYoutubePlugin( + content::RenderView* render_view, + WebFrame* frame, + const WebPluginParams& params) { + const base::StringPiece template_html( + ResourceBundle::GetSharedInstance().GetRawDataResource( + IDR_MOBILE_YOUTUBE_PLUGIN_HTML)); + + base::DictionaryValue values; + values.SetString("video_id", GetYoutubeVideoId(params)); + std::string html_data = webui::GetI18nTemplateHtml(template_html, &values); + + // |youtube_plugin| will destroy itself when its WebViewPlugin is going away. + PluginPlaceholder* youtube_plugin = new PluginPlaceholder( + render_view, frame, params, html_data, params.mimeType); + return youtube_plugin; +} +#endif + +PluginPlaceholder::PluginPlaceholder(content::RenderView* render_view, + WebFrame* frame, + const WebPluginParams& params, + 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))), + 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), + context_menu_request_id_(0) { + RenderThread::Get()->AddObserver(this); +} + +PluginPlaceholder::~PluginPlaceholder() { + RenderThread::Get()->RemoveObserver(this); + if (context_menu_request_id_) + render_view()->CancelContextMenu(context_menu_request_id_); + +#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))); +#if defined(ENABLE_MOBILE_YOUTUBE_PLUGIN) + BindCallback("openYoutubeURL", + base::Bind(&PluginPlaceholder::OpenYoutubeUrlCallback, + base::Unretained(this))); +#endif +} + +bool PluginPlaceholder::OnMessageReceived(const IPC::Message& message) { +#if defined(ENABLE_PLUGIN_INSTALLATION) + 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_HANDLER(ChromeViewMsg_CancelledDownloadingPlugin, + OnCancelledDownloadingPlugin) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + + if (handled) + return true; +#endif + + // 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(PrerenderMsg_SetIsPrerendering, OnSetIsPrerendering) + IPC_END_MESSAGE_MAP() + + return false; +} + +void PluginPlaceholder::ReplacePlugin(WebPlugin* new_plugin) { + CHECK(plugin_); + if (!new_plugin) { + PluginUMAReporter::GetInstance()->ReportPluginMissing( + plugin_params_.mimeType.utf8(), + plugin_params_.url); + return; + } + + WebPluginContainer* container = plugin_->container(); + // Set the new plug-in on the container before initializing it. + container->setPlugin(new_plugin); + // Save the element in case the plug-in is removed from the page during + // initialization. + WebElement element = container->element(); + if (!new_plugin->initialize(container)) { + // We couldn't initialize the new plug-in. Restore the old one and abort. + container->setPlugin(plugin_); + return; + } + + // The plug-in has been removed from the page. Destroy the old plug-in + // (which will destroy us). + if (!element.pluginContainer()) { + plugin_->destroy(); + return; + } + + // During initialization, the new plug-in might have replaced itself in turn + // with another plug-in. Make sure not to use the passed in |new_plugin| after + // this point. + new_plugin = container->plugin(); + + plugin_->RestoreTitleText(); + container->invalidate(); + container->reportGeometry(); + plugin_->ReplayReceivedData(new_plugin); + plugin_->destroy(); +} + +void PluginPlaceholder::HidePlugin() { + 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"; + 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"; + WebNode parent = element; + while (!parent.parentNode().isNull()) { + parent = parent.parentNode(); + if (!parent.isElementNode()) + continue; + element = parent.toConst<WebElement>(); + if (element.hasAttribute("style")) { + std::string style_str = element.getAttribute("style").utf8(); + if (RE2::PartialMatch(style_str, width_str) && + RE2::PartialMatch(style_str, height_str)) + element.setAttribute("style", "display: none;"); + } + } + } +} + +void PluginPlaceholder::WillDestroyPlugin() { + delete this; +} + +#if defined(ENABLE_PLUGIN_INSTALLATION) +void PluginPlaceholder::OnDidNotFindMissingPlugin() { + SetMessage(l10n_util::GetStringUTF16(IDS_PLUGIN_NOT_FOUND)); +} + +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; + plugin_name_ = plugin_name; +} + +void PluginPlaceholder::OnStartedDownloadingPlugin() { + SetMessage(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOADING, plugin_name_)); +} + +void PluginPlaceholder::OnFinishedDownloadingPlugin() { + bool is_installing = + status_->value == ChromeViewHostMsg_GetPluginInfo_Status::kNotFound; + SetMessage(l10n_util::GetStringFUTF16( + is_installing ? IDS_PLUGIN_INSTALLING : IDS_PLUGIN_UPDATING, + plugin_name_)); +} + +void PluginPlaceholder::OnErrorDownloadingPlugin(const std::string& error) { + SetMessage(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOAD_ERROR, + UTF8ToUTF16(error))); +} + +void PluginPlaceholder::OnCancelledDownloadingPlugin() { + SetMessage(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOAD_CANCELLED, + plugin_name_)); +} +#endif // defined(ENABLE_PLUGIN_INSTALLATION) + +void PluginPlaceholder::PluginListChanged() { + if (!frame_) + return; + WebDocument document = frame_->top()->document(); + if (document.isNull()) + return; + + ChromeViewHostMsg_GetPluginInfo_Output output; + std::string mime_type(plugin_params_.mimeType.utf8()); + render_view()->Send(new ChromeViewHostMsg_GetPluginInfo( + routing_id(), GURL(plugin_params_.url), document.url(), + mime_type, &output)); + if (output.status.value == status_->value) + return; + WebPlugin* new_plugin = chrome::ChromeContentRendererClient::CreatePlugin( + render_view(), frame_, plugin_params_, output); + ReplacePlugin(new_plugin); +} + +void PluginPlaceholder::OnMenuAction(int request_id, unsigned action) { + DCHECK_EQ(context_menu_request_id_, request_id); + if (g_last_active_menu != this) + return; + switch (action) { + 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::OnMenuClosed(int request_id) { + DCHECK_EQ(context_menu_request_id_, request_id); + context_menu_request_id_ = 0; +} + +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::ShowContextMenu(const WebMouseEvent& event) { + if (context_menu_request_id_) + return; // Don't allow nested context menu requests. + + content::ContextMenuParams params; + + content::MenuItem name_item; + name_item.label = title_; + params.custom_items.push_back(name_item); + + content::MenuItem separator_item; + separator_item.type = content::MenuItem::SEPARATOR; + params.custom_items.push_back(separator_item); + + if (!plugin_info_.path.value().empty()) { + content::MenuItem 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 = l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_PLUGIN_RUN); + params.custom_items.push_back(run_item); + } + + content::MenuItem hide_item; + hide_item.action = chrome::MENU_COMMAND_PLUGIN_HIDE; + hide_item.enabled = true; + hide_item.label = l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_PLUGIN_HIDE); + params.custom_items.push_back(hide_item); + + params.x = event.windowX; + params.y = event.windowY; + + context_menu_request_id_ = render_view()->ShowContextMenu(this, params); + g_last_active_menu = this; +} + +void PluginPlaceholder::OnLoadBlockedPlugins(const std::string& identifier) { + if (!identifier.empty() && identifier != identifier_) + return; + + 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; + } + + // TODO(mmenke): In the case of prerendering, feed into + // ChromeContentRendererClient::CreatePlugin instead, to + // reduce the chance of future regressions. + 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(); +} + +#if defined(ENABLE_MOBILE_YOUTUBE_PLUGIN) +void PluginPlaceholder::OpenYoutubeUrlCallback(const CppArgumentList& args, + CppVariant* result) { + std::string youtube("vnd.youtube:"); + GURL url(youtube.append(GetYoutubeVideoId(plugin_params_))); + WebURLRequest request; + request.initialize(); + request.setURL(url); + render_view()->LoadURLExternally( + frame_, request, WebKit::WebNavigationPolicyNewForegroundTab); +} + +bool PluginPlaceholder::IsValidYouTubeVideo(const std::string& path) { + unsigned len = strlen(kSlashVSlash); + + // check for more than just /v/ or /e/. + if (path.length() <= len) + return false; + + std::string str = StringToLowerASCII(path); + // Youtube flash url can start with /v/ or /e/. + if (strncmp(str.data(), kSlashVSlash, len) != 0 && + strncmp(str.data(), kSlashESlash, len) != 0) + return false; + + // Start after /v/ + for (unsigned i = len; i < path.length(); i++) { + char c = str[i]; + if (isalpha(c) || isdigit(c) || c == '_' || c == '-') + continue; + // The url can have more parameters such as &hl=en after the video id. + // Once we start seeing extra parameters we can return true. + return c == '&' && i > len; + } + return true; +} + +bool PluginPlaceholder::IsYouTubeURL(const GURL& url, + const std::string& mime_type) { + std::string host = url.host(); + bool is_youtube = EndsWith(host, "youtube.com", true) || + EndsWith(host, "youtube-nocookie.com", true); + + return is_youtube && IsValidYouTubeVideo(url.path()) && + LowerCaseEqualsASCII(mime_type, content::kFlashPluginSwfMimeType); +} +#endif diff --git a/chrome/renderer/plugins/plugin_placeholder.h b/chrome/renderer/plugins/plugin_placeholder.h new file mode 100644 index 0000000..7ec95bae --- /dev/null +++ b/chrome/renderer/plugins/plugin_placeholder.h @@ -0,0 +1,193 @@ +// 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_PLUGIN_PLACEHOLDER_H_ +#define CHROME_RENDERER_PLUGINS_PLUGIN_PLACEHOLDER_H_ + +#include "chrome/renderer/plugins/webview_plugin.h" +#include "content/public/common/webplugininfo.h" +#include "content/public/renderer/context_menu_client.h" +#include "content/public/renderer/render_process_observer.h" +#include "content/public/renderer/render_view_observer.h" +#include "third_party/WebKit/public/web/WebPluginParams.h" +#include "webkit/renderer/cpp_bound_class.h" + +struct ChromeViewHostMsg_GetPluginInfo_Status; + +namespace content { +struct WebPluginInfo; +} + +// 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 webkit_glue::CppBoundClass, + public WebViewPlugin::Delegate, + public content::ContextMenuClient { + 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* CreateErrorPlugin( + content::RenderView* render_view, + const base::FilePath& plugin_path); + + static PluginPlaceholder* CreateBlockedPlugin( + content::RenderView* render_view, + WebKit::WebFrame* frame, + const WebKit::WebPluginParams& params, + const content::WebPluginInfo& info, + const std::string& identifier, + const string16& name, + int resource_id, + const string16& message); + +#if defined(ENABLE_MOBILE_YOUTUBE_PLUGIN) + // Placeholder for old style embedded youtube video on mobile device. For old + // style embedded youtube video, it has a url in the form of + // http://www.youtube.com/v/VIDEO_ID. This placeholder replaces the url with a + // simple html page and clicking the play image redirects the user to the + // mobile youtube app. + static PluginPlaceholder* CreateMobileYoutubePlugin( + content::RenderView* render_view, + WebKit::WebFrame* frame, + const WebKit::WebPluginParams& params); +#endif + + 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 + +#if defined(ENABLE_MOBILE_YOUTUBE_PLUGIN) + // Whether this is a youtube url. + static bool IsYouTubeURL(const GURL& url, const std::string& mime_type); +#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, + const string16& title); + + virtual ~PluginPlaceholder(); + + // WebViewPlugin::Delegate methods: + virtual void BindWebFrame(WebKit::WebFrame* frame) OVERRIDE; + virtual void WillDestroyPlugin() OVERRIDE; + virtual void ShowContextMenu(const WebKit::WebMouseEvent&) OVERRIDE; + + // content::RenderViewObserver methods: + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; + + // content::RenderProcessObserver methods: + virtual void PluginListChanged() OVERRIDE; + + // content::ContextMenuClient methods: + virtual void OnMenuAction(int request_id, unsigned action) OVERRIDE; + virtual void OnMenuClosed(int request_id) 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 webkit_glue::CppArgumentList& args, + webkit_glue::CppVariant* result); + + // Hide the blocked plugin by calling HidePlugin(). + // Takes no arguments, and returns nothing. + void HideCallback(const webkit_glue::CppArgumentList& args, + webkit_glue::CppVariant* result); + + // Opens chrome://plugins in a new tab. + // Takes no arguments, and returns nothing. + void OpenAboutPluginsCallback(const webkit_glue::CppArgumentList& args, + webkit_glue::CppVariant* result); + + void DidFinishLoadingCallback(const webkit_glue::CppArgumentList& args, + webkit_glue::CppVariant* result); + + void OnLoadBlockedPlugins(const std::string& identifier); + void OnSetIsPrerendering(bool is_prerendering); +#if defined(ENABLE_PLUGIN_INSTALLATION) + void OnDidNotFindMissingPlugin(); + void OnFoundMissingPlugin(const string16& plugin_name); + void OnStartedDownloadingPlugin(); + void OnFinishedDownloadingPlugin(); + void OnErrorDownloadingPlugin(const std::string& error); + void OnCancelledDownloadingPlugin(); +#endif + +#if defined(ENABLE_MOBILE_YOUTUBE_PLUGIN) + // Check whether the url is valid. + static bool IsValidYouTubeVideo(const std::string& path); + + // Opens a youtube app in the current tab. + void OpenYoutubeUrlCallback(const webkit_glue::CppArgumentList& args, + webkit_glue::CppVariant* result); +#endif + + void SetMessage(const string16& message); + void UpdateMessage(); + + WebKit::WebFrame* frame_; + WebKit::WebPluginParams plugin_params_; + WebViewPlugin* plugin_; + + content::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_; + string16 plugin_name_; + std::string identifier_; + int context_menu_request_id_; // Nonzero when request pending. + + DISALLOW_COPY_AND_ASSIGN(PluginPlaceholder); +}; + +#endif // CHROME_RENDERER_PLUGINS_PLUGIN_PLACEHOLDER_H_ diff --git a/chrome/renderer/plugins/plugin_uma.cc b/chrome/renderer/plugins/plugin_uma.cc index 37fc323..b6c8764 100644 --- a/chrome/renderer/plugins/plugin_uma.cc +++ b/chrome/renderer/plugins/plugin_uma.cc @@ -23,15 +23,32 @@ const char kQuickTimeType[] = "video/quicktime"; // Arrays containing file extensions connected with specific plugins. // Note: THE ARRAYS MUST BE SORTED BECAUSE BINARY SEARCH IS USED ON THEM! -const char* kWindowsMediaPlayerExtensions[] = {".asx"}; +const char* kWindowsMediaPlayerExtensions[] = { + ".asx" +}; -const char* kRealPlayerExtensions[] = {".ra", ".ram", ".rm", - ".rmm", ".rmp", ".rpm"}; +const char* kRealPlayerExtensions[] = { + ".ra", + ".ram", + ".rm", + ".rmm", + ".rmp", + ".rpm" +}; -const char* kQuickTimeExtensions[] = {".moov", ".mov", ".qif", - ".qt", ".qti", ".qtif"}; +const char* kQuickTimeExtensions[] = { + ".moov", + ".mov", + ".qif", + ".qt", + ".qti", + ".qtif" +}; -const char* kShockwaveFlashExtensions[] = {".spl", ".swf"}; +const char* kShockwaveFlashExtensions[] = { + ".spl", + ".swf" +}; } // namespace. @@ -66,22 +83,23 @@ PluginUMAReporter* PluginUMAReporter::GetInstance() { return Singleton<PluginUMAReporter>::get(); } -void PluginUMAReporter::ReportPluginMissing(const std::string& plugin_mime_type, - const GURL& plugin_src) { +void PluginUMAReporter::ReportPluginMissing( + const std::string& plugin_mime_type, const GURL& plugin_src) { report_sender_->SendPluginUMA(MISSING_PLUGIN, GetPluginType(plugin_mime_type, plugin_src)); } void PluginUMAReporter::ReportPluginDisabled( - const std::string& plugin_mime_type, - const GURL& plugin_src) { + const std::string& plugin_mime_type, const GURL& plugin_src) { report_sender_->SendPluginUMA(DISABLED_PLUGIN, GetPluginType(plugin_mime_type, plugin_src)); } -PluginUMAReporter::PluginUMAReporter() : report_sender_(new UMASenderImpl()) {} +PluginUMAReporter::PluginUMAReporter() : report_sender_(new UMASenderImpl()) { +} -PluginUMAReporter::~PluginUMAReporter() {} +PluginUMAReporter::~PluginUMAReporter() { +} // static. bool PluginUMAReporter::CompareCStrings(const char* first, const char* second) { @@ -111,8 +129,7 @@ void PluginUMAReporter::ExtractFileExtension(const GURL& src, } PluginUMAReporter::PluginType PluginUMAReporter::GetPluginType( - const std::string& plugin_mime_type, - const GURL& plugin_src) { + const std::string& plugin_mime_type, const GURL& plugin_src) { // If we know plugin's mime type, we use it to determine plugin's type. Else, // we try to determine plugin type using plugin source's extension. if (!plugin_mime_type.empty()) diff --git a/chrome/renderer/plugins/plugin_uma.h b/chrome/renderer/plugins/plugin_uma.h index ae63c67..22a10f1 100644 --- a/chrome/renderer/plugins/plugin_uma.h +++ b/chrome/renderer/plugins/plugin_uma.h @@ -86,3 +86,4 @@ class PluginUMAReporter { }; #endif // CHROME_RENDERER_PLUGINS_PLUGIN_UMA_H_ + diff --git a/chrome/renderer/plugins/plugin_uma_unittest.cc b/chrome/renderer/plugins/plugin_uma_unittest.cc index 7bce210..587ab66 100644 --- a/chrome/renderer/plugins/plugin_uma_unittest.cc +++ b/chrome/renderer/plugins/plugin_uma_unittest.cc @@ -43,8 +43,9 @@ TEST_F(PluginUMATest, Silverlight) { } TEST_F(PluginUMATest, RealPlayer) { - ExpectPluginType( - PluginUMAReporter::REALPLAYER, "audio/x-pn-realaudio", GURL("some url")); + ExpectPluginType(PluginUMAReporter::REALPLAYER, + "audio/x-pn-realaudio", + GURL("some url")); ExpectPluginType(PluginUMAReporter::REALPLAYER, "audio/x-pn-realaudio-some-sufix", GURL("some url")); @@ -54,8 +55,9 @@ TEST_F(PluginUMATest, RealPlayer) { } TEST_F(PluginUMATest, Java) { - ExpectPluginType( - PluginUMAReporter::JAVA, "application/x-java-applet", GURL("some url")); + ExpectPluginType(PluginUMAReporter::JAVA, + "application/x-java-applet", + GURL("some url")); ExpectPluginType(PluginUMAReporter::JAVA, "application/x-java-applet-some-sufix", GURL("some url")); @@ -65,8 +67,9 @@ TEST_F(PluginUMATest, Java) { } TEST_F(PluginUMATest, QuickTime) { - ExpectPluginType( - PluginUMAReporter::QUICKTIME, "video/quicktime", GURL("some url")); + ExpectPluginType(PluginUMAReporter::QUICKTIME, + "video/quicktime", + GURL("some url")); ExpectPluginType(PluginUMAReporter::UNSUPPORTED_MIMETYPE, "video/quicktime-sufix", GURL("some url")); @@ -155,8 +158,9 @@ TEST_F(PluginUMATest, BySrcExtension) { } TEST_F(PluginUMATest, CaseSensitivity) { - ExpectPluginType( - PluginUMAReporter::QUICKTIME, "video/QUICKTIME", GURL("http://file.aaa")); + ExpectPluginType(PluginUMAReporter::QUICKTIME, + "video/QUICKTIME", + GURL("http://file.aaa")); ExpectPluginType( PluginUMAReporter::QUICKTIME, std::string(), GURL("http://file.MoV")); } diff --git a/components/plugins/renderer/webview_plugin.cc b/chrome/renderer/plugins/webview_plugin.cc index 20969d5..2853a313 100644 --- a/components/plugins/renderer/webview_plugin.cc +++ b/chrome/renderer/plugins/webview_plugin.cc @@ -1,12 +1,11 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright (c) 2013 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 "components/plugins/renderer/webview_plugin.h" +#include "chrome/renderer/plugins/webview_plugin.h" #include "base/message_loop/message_loop.h" #include "base/metrics/histogram.h" -#include "base/safe_numerics.h" #include "content/public/renderer/web_preferences.h" #include "skia/ext/platform_canvas.h" #include "third_party/WebKit/public/platform/WebSize.h" @@ -43,7 +42,9 @@ using WebKit::WebVector; using WebKit::WebView; WebViewPlugin::WebViewPlugin(WebViewPlugin::Delegate* delegate) - : delegate_(delegate), container_(NULL), finished_loading_(false) { + : delegate_(delegate), + container_(NULL), + finished_loading_(false) { web_view_ = WebView::create(this); web_view_->initializeMainFrame(this); } @@ -60,24 +61,21 @@ WebViewPlugin* WebViewPlugin::Create(WebViewPlugin::Delegate* delegate, return plugin; } -WebViewPlugin::~WebViewPlugin() { web_view_->close(); } +WebViewPlugin::~WebViewPlugin() { + web_view_->close(); +} void WebViewPlugin::ReplayReceivedData(WebPlugin* plugin) { if (!response_.isNull()) { plugin->didReceiveResponse(response_); size_t total_bytes = 0; - for (std::list<std::string>::iterator it = data_.begin(); it != data_.end(); - ++it) { - plugin->didReceiveData( - it->c_str(), base::checked_numeric_cast<int, size_t>(it->length())); + for (std::list<std::string>::iterator it = data_.begin(); + it != data_.end(); ++it) { + plugin->didReceiveData(it->c_str(), it->length()); total_bytes += it->length(); } - UMA_HISTOGRAM_MEMORY_KB( - "PluginDocument.Memory", - (base::checked_numeric_cast<int, size_t>(total_bytes / 1024))); - UMA_HISTOGRAM_COUNTS( - "PluginDocument.NumChunks", - (base::checked_numeric_cast<int, size_t>(data_.size()))); + UMA_HISTOGRAM_MEMORY_KB("PluginDocument.Memory", (total_bytes / 1024)); + UMA_HISTOGRAM_COUNTS("PluginDocument.NumChunks", data_.size()); } if (finished_loading_) { plugin->didFinishLoading(); @@ -92,7 +90,9 @@ void WebViewPlugin::RestoreTitleText() { container_->element().setAttribute("title", old_title_); } -WebPluginContainer* WebViewPlugin::container() const { return container_; } +WebPluginContainer* WebViewPlugin::container() const { + return container_; +} bool WebViewPlugin::initialize(WebPluginContainer* container) { container_ = container; @@ -110,11 +110,17 @@ void WebViewPlugin::destroy() { base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); } -NPObject* WebViewPlugin::scriptableObject() { return NULL; } +NPObject* WebViewPlugin::scriptableObject() { + return NULL; +} -struct _NPP* WebViewPlugin::pluginNPP() { return NULL; } +struct _NPP* WebViewPlugin::pluginNPP() { + return NULL; +} -bool WebViewPlugin::getFormValue(WebString& value) { return false; } +bool WebViewPlugin::getFormValue(WebString& value) { + return false; +} void WebViewPlugin::paint(WebCanvas* canvas, const WebRect& rect) { gfx::Rect paint_rect = gfx::IntersectRects(rect_, rect); @@ -133,17 +139,18 @@ void WebViewPlugin::paint(WebCanvas* canvas, const WebRect& rect) { } // Coordinates are relative to the containing window. -void WebViewPlugin::updateGeometry(const WebRect& frame_rect, - const WebRect& clip_rect, - const WebVector<WebRect>& cut_out_rects, - bool is_visible) { +void WebViewPlugin::updateGeometry( + const WebRect& frame_rect, const WebRect& clip_rect, + const WebVector<WebRect>& cut_out_rects, bool is_visible) { if (static_cast<gfx::Rect>(frame_rect) != rect_) { rect_ = frame_rect; web_view_->resize(WebSize(frame_rect.width, frame_rect.height)); } } -bool WebViewPlugin::acceptsInputEvents() { return true; } +bool WebViewPlugin::acceptsInputEvents() { + return true; +} bool WebViewPlugin::handleInputEvent(const WebInputEvent& event, WebCursorInfo& cursor) { @@ -186,7 +193,9 @@ void WebViewPlugin::didFailLoading(const WebURLError& error) { error_.reset(new WebURLError(error)); } -bool WebViewPlugin::acceptsLoadDrops() { return false; } +bool WebViewPlugin::acceptsLoadDrops() { + return false; +} void WebViewPlugin::setToolTipText(const WebString& text, WebKit::WebTextDirection hint) { diff --git a/components/plugins/renderer/webview_plugin.h b/chrome/renderer/plugins/webview_plugin.h index 13e480c..791539c 100644 --- a/components/plugins/renderer/webview_plugin.h +++ b/chrome/renderer/plugins/webview_plugin.h @@ -1,9 +1,9 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// 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 COMPONENTS_PLUGINS_RENDERER_WEBVIEW_PLUGIN_H_ -#define COMPONENTS_PLUGINS_RENDERER_WEBVIEW_PLUGIN_H_ +#ifndef CHROME_RENDERER_PLUGINS_WEBVIEW_PLUGIN_H_ +#define CHROME_RENDERER_PLUGINS_WEBVIEW_PLUGIN_H_ #include <list> @@ -53,10 +53,11 @@ class WebViewPlugin : public WebKit::WebPlugin, // Convenience method to set up a new WebViewPlugin using |preferences| // and displaying |html_data|. |url| should be a (fake) chrome:// URL; it is // only used for navigation and never actually resolved. - static WebViewPlugin* Create(Delegate* delegate, - const WebPreferences& preferences, - const std::string& html_data, - const GURL& url); + static WebViewPlugin* Create( + Delegate* delegate, + const WebPreferences& preferences, + const std::string& html_data, + const GURL& url); WebKit::WebView* web_view() { return web_view_; } @@ -81,10 +82,8 @@ class WebViewPlugin : public WebKit::WebPlugin, // Coordinates are relative to the containing window. virtual void updateGeometry( - const WebKit::WebRect& frame_rect, - const WebKit::WebRect& clip_rect, - const WebKit::WebVector<WebKit::WebRect>& cut_out_rects, - bool is_visible); + const WebKit::WebRect& frame_rect, const WebKit::WebRect& clip_rect, + const WebKit::WebVector<WebKit::WebRect>& cut_out_rects, bool is_visible); virtual void updateFocus(bool) {} virtual void updateVisibility(bool) {} @@ -99,8 +98,8 @@ class WebViewPlugin : public WebKit::WebPlugin, virtual void didFailLoading(const WebKit::WebURLError& error); // Called in response to WebPluginContainer::loadFrameRequest - virtual void didFinishLoadingFrameRequest(const WebKit::WebURL& url, - void* notifyData) {} + virtual void didFinishLoadingFrameRequest( + const WebKit::WebURL& url, void* notifyData) {} virtual void didFailLoadingFrameRequest(const WebKit::WebURL& url, void* notify_data, const WebKit::WebURLError& error) {} @@ -152,4 +151,4 @@ class WebViewPlugin : public WebKit::WebPlugin, WebKit::WebString old_title_; }; -#endif // COMPONENTS_PLUGINS_RENDERER_WEBVIEW_PLUGIN_H_ +#endif // CHROME_RENDERER_PLUGINS_WEBVIEW_PLUGIN_H_ diff --git a/components/components.gyp b/components/components.gyp index 2e588d1..e16eda3 100644 --- a/components/components.gyp +++ b/components/components.gyp @@ -19,7 +19,6 @@ 'json_schema.gypi', 'navigation_interception.gypi', 'onc.gypi', - 'plugins.gypi', 'policy.gypi', 'sessions.gypi', 'startup_metric_utils.gypi', diff --git a/components/components_tests.gypi b/components/components_tests.gypi index b960bfa..675b2b5 100644 --- a/components/components_tests.gypi +++ b/components/components_tests.gypi @@ -70,7 +70,7 @@ '../content/content.gyp:test_support_content', '../skia/skia.gyp:skia', 'navigation_interception', - + # Dependencies of policy 'policy_component', diff --git a/components/plugins.gypi b/components/plugins.gypi deleted file mode 100644 index 8ef3ea0..0000000 --- a/components/plugins.gypi +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright 2013 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. - -{ - 'conditions': [ - ['OS != "ios"', { - - 'targets': [ - { - 'target_name': 'plugins_renderer', - 'type': 'static_library', - 'dependencies': [ - '../skia/skia.gyp:skia', - '../third_party/re2/re2.gyp:re2', - '../third_party/WebKit/public/blink.gyp:blink', - ], - 'include_dirs': [ - '..', - ], - 'sources': [ - 'plugins/renderer/plugin_placeholder.cc', - 'plugins/renderer/plugin_placeholder.h', - 'plugins/renderer/webview_plugin.cc', - 'plugins/renderer/webview_plugin.h', - ], - 'conditions' : [ - ['OS=="android"', { - 'sources': [ - 'plugins/renderer/mobile_youtube_plugin.cc', - 'plugins/renderer/mobile_youtube_plugin.h', - ] - }], - ], - }, - ] - }] - ] -} diff --git a/components/plugins/OWNERS b/components/plugins/OWNERS deleted file mode 100644 index 00985a8..0000000 --- a/components/plugins/OWNERS +++ /dev/null @@ -1 +0,0 @@ -bauerb@chromium.org diff --git a/components/plugins/renderer/DEPS b/components/plugins/renderer/DEPS deleted file mode 100644 index 40b689d..0000000 --- a/components/plugins/renderer/DEPS +++ /dev/null @@ -1,13 +0,0 @@ -include_rules = [ - "+net", - - "+content/public/renderer", - "+content/public/common", - "+content/public/test", - "+third_party/WebKit/public", - "+third_party/re2", - "+skia", - "+webkit/common", - "+webkit/renderer", - "+ui/webui", -] diff --git a/components/plugins/renderer/mobile_youtube_plugin.cc b/components/plugins/renderer/mobile_youtube_plugin.cc deleted file mode 100644 index 3312312..0000000 --- a/components/plugins/renderer/mobile_youtube_plugin.cc +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright 2013 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 "components/plugins/renderer/mobile_youtube_plugin.h" - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/strings/string_piece.h" -#include "base/strings/string_util.h" -#include "base/values.h" -#include "content/public/common/content_constants.h" -#include "content/public/renderer/render_view.h" -#include "third_party/WebKit/public/web/WebFrame.h" -#include "ui/webui/jstemplate_builder.h" - -using WebKit::WebFrame; -using WebKit::WebPlugin; -using WebKit::WebURLRequest; - -const char* const kSlashVSlash = "/v/"; -const char* const kSlashESlash = "/e/"; - -namespace { - -std::string GetYoutubeVideoId(const WebKit::WebPluginParams& params) { - GURL url(params.url); - std::string video_id = url.path().substr(strlen(kSlashVSlash)); - - // Extract just the video id - size_t video_id_end = video_id.find('&'); - if (video_id_end != std::string::npos) - video_id = video_id.substr(0, video_id_end); - return video_id; -} - -std::string HtmlData(const WebKit::WebPluginParams& params, - base::StringPiece template_html) { - base::DictionaryValue values; - values.SetString("video_id", GetYoutubeVideoId(params)); - return webui::GetI18nTemplateHtml(template_html, &values); -} - -bool IsValidYouTubeVideo(const std::string& path) { - unsigned len = strlen(kSlashVSlash); - - // check for more than just /v/ or /e/. - if (path.length() <= len) - return false; - - std::string str = StringToLowerASCII(path); - // Youtube flash url can start with /v/ or /e/. - if (strncmp(str.data(), kSlashVSlash, len) != 0 && - strncmp(str.data(), kSlashESlash, len) != 0) - return false; - - // Start after /v/ - for (unsigned i = len; i < path.length(); i++) { - char c = str[i]; - if (isalpha(c) || isdigit(c) || c == '_' || c == '-') - continue; - // The url can have more parameters such as &hl=en after the video id. - // Once we start seeing extra parameters we can return true. - return c == '&' && i > len; - } - return true; -} - -} // namespace - -namespace plugins { - -MobileYouTubePlugin::MobileYouTubePlugin(content::RenderView* render_view, - WebKit::WebFrame* frame, - const WebKit::WebPluginParams& params, - base::StringPiece& template_html, - GURL placeholderDataUrl) - : PluginPlaceholder(render_view, - frame, - params, - HtmlData(params, template_html), - placeholderDataUrl) {} - -// static -bool MobileYouTubePlugin::IsYouTubeURL(const GURL& url, - const std::string& mime_type) { - std::string host = url.host(); - bool is_youtube = EndsWith(host, "youtube.com", true) || - EndsWith(host, "youtube-nocookie.com", true); - - return is_youtube && IsValidYouTubeVideo(url.path()) && - LowerCaseEqualsASCII(mime_type, content::kFlashPluginSwfMimeType); -} - -void MobileYouTubePlugin::OpenYoutubeUrlCallback( - const webkit_glue::CppArgumentList& args, - webkit_glue::CppVariant* result) { - std::string youtube("vnd.youtube:"); - GURL url(youtube.append(GetYoutubeVideoId(GetPluginParams()))); - WebURLRequest request; - request.initialize(); - request.setURL(url); - render_view()->LoadURLExternally( - GetFrame(), request, WebKit::WebNavigationPolicyNewForegroundTab); -} -void MobileYouTubePlugin::BindWebFrame(WebFrame* frame) { - PluginPlaceholder::BindWebFrame(frame); - BindCallback("openYoutubeURL", - base::Bind(&MobileYouTubePlugin::OpenYoutubeUrlCallback, - base::Unretained(this))); -} - -} // namespace plugins diff --git a/components/plugins/renderer/mobile_youtube_plugin.h b/components/plugins/renderer/mobile_youtube_plugin.h deleted file mode 100644 index 9a88ce0..0000000 --- a/components/plugins/renderer/mobile_youtube_plugin.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2013 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 COMPONENTS_PLUGINS_RENDERER_MOBILE_YOUTUBE_PLUGIN_H_ -#define COMPONENTS_PLUGINS_RENDERER_MOBILE_YOUTUBE_PLUGIN_H_ - -#include "components/plugins/renderer/plugin_placeholder.h" - -namespace plugins { - -// Class representing placeholders for old style embedded youtube video on -// mobile device. For old style embedded youtube video, it has a url in the form -// of http://www.youtube.com/v/VIDEO_ID. This placeholder replaces the url with -// a simple html page and clicking the play image redirects the user to the -// mobile youtube app. -class MobileYouTubePlugin : public PluginPlaceholder { - public: - MobileYouTubePlugin(content::RenderView* render_view, - WebKit::WebFrame* frame, - const WebKit::WebPluginParams& params, - base::StringPiece& template_html, - GURL placeholderDataUrl); - - // Whether this is a youtube url. - static bool IsYouTubeURL(const GURL& url, const std::string& mime_type); - - private: - // Opens a youtube app in the current tab. - void OpenYoutubeUrlCallback(const webkit_glue::CppArgumentList& args, - webkit_glue::CppVariant* result); - - // WebViewPlugin::Delegate (via PluginPlaceholder) method - virtual void BindWebFrame(WebKit::WebFrame* frame) OVERRIDE; - - DISALLOW_COPY_AND_ASSIGN(MobileYouTubePlugin); -}; - -} // namespace plugins - -#endif // COMPONENTS_PLUGINS_RENDERER_MOBILE_YOUTUBE_PLUGIN_H_ diff --git a/components/plugins/renderer/plugin_placeholder.cc b/components/plugins/renderer/plugin_placeholder.cc deleted file mode 100644 index 03d13b1..0000000 --- a/components/plugins/renderer/plugin_placeholder.cc +++ /dev/null @@ -1,247 +0,0 @@ -// Copyright 2013 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 "components/plugins/renderer/plugin_placeholder.h" - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/json/string_escape.h" -#include "base/strings/string_piece.h" -#include "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" -#include "base/values.h" -#include "content/public/common/content_constants.h" -#include "content/public/common/context_menu_params.h" -#include "content/public/renderer/render_thread.h" -#include "content/public/renderer/render_view.h" -#include "third_party/WebKit/public/web/WebDocument.h" -#include "third_party/WebKit/public/web/WebElement.h" -#include "third_party/WebKit/public/web/WebFrame.h" -#include "third_party/WebKit/public/web/WebInputEvent.h" -#include "third_party/WebKit/public/web/WebPluginContainer.h" -#include "third_party/WebKit/public/web/WebScriptSource.h" -#include "third_party/WebKit/public/web/WebView.h" -#include "third_party/re2/re2/re2.h" - -using content::RenderThread; -using WebKit::WebElement; -using WebKit::WebFrame; -using WebKit::WebMouseEvent; -using WebKit::WebNode; -using WebKit::WebPlugin; -using WebKit::WebPluginContainer; -using WebKit::WebPluginParams; -using WebKit::WebScriptSource; -using WebKit::WebURLRequest; -using webkit_glue::CppArgumentList; -using webkit_glue::CppVariant; - -namespace plugins { - -PluginPlaceholder::PluginPlaceholder(content::RenderView* render_view, - WebFrame* frame, - const WebPluginParams& params, - const std::string& html_data, - GURL placeholderDataUrl) - : content::RenderViewObserver(render_view), - frame_(frame), - plugin_params_(params), - plugin_(WebViewPlugin::Create(this, - render_view->GetWebkitPreferences(), - html_data, - placeholderDataUrl)), - is_blocked_for_prerendering_(false), - allow_loading_(false), - hidden_(false), - finished_loading_(false) {} - -PluginPlaceholder::~PluginPlaceholder() {} - -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("didFinishLoading", - base::Bind(&PluginPlaceholder::DidFinishLoadingCallback, - base::Unretained(this))); -} - -void PluginPlaceholder::ReplacePlugin(WebPlugin* new_plugin) { - CHECK(plugin_); - if (!new_plugin) return; - WebPluginContainer* container = plugin_->container(); - // Set the new plug-in on the container before initializing it. - container->setPlugin(new_plugin); - // Save the element in case the plug-in is removed from the page during - // initialization. - WebElement element = container->element(); - if (!new_plugin->initialize(container)) { - // We couldn't initialize the new plug-in. Restore the old one and abort. - container->setPlugin(plugin_); - return; - } - - // The plug-in has been removed from the page. Destroy the old plug-in - // (which will destroy us). - if (!element.pluginContainer()) { - plugin_->destroy(); - return; - } - - // During initialization, the new plug-in might have replaced itself in turn - // with another plug-in. Make sure not to use the passed in |new_plugin| after - // this point. - new_plugin = container->plugin(); - - plugin_->RestoreTitleText(); - container->invalidate(); - container->reportGeometry(); - plugin_->ReplayReceivedData(new_plugin); - plugin_->destroy(); -} - -void PluginPlaceholder::HidePlugin() { - 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"; - 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"; - WebNode parent = element; - while (!parent.parentNode().isNull()) { - parent = parent.parentNode(); - if (!parent.isElementNode()) - continue; - element = parent.toConst<WebElement>(); - if (element.hasAttribute("style")) { - std::string style_str = element.getAttribute("style").utf8(); - if (RE2::PartialMatch(style_str, width_str) && - RE2::PartialMatch(style_str, height_str)) - element.setAttribute("style", "display: none;"); - } - } - } -} - -void PluginPlaceholder::WillDestroyPlugin() { delete this; } - -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::ShowContextMenu(const WebMouseEvent& event) { - // Does nothing by default. Will be overridden if a specific browser wants - // a context menu. - return; -} - -void PluginPlaceholder::OnLoadBlockedPlugins(const std::string& identifier) { - if (!identifier.empty() && identifier != identifier_) - return; - - 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; - } - - // TODO(mmenke): In the case of prerendering, feed into - // ChromeContentRendererClient::CreatePlugin instead, to - // reduce the chance of future regressions. - 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::DidFinishLoadingCallback(const CppArgumentList& args, - CppVariant* result) { - finished_loading_ = true; - if (message_.length() > 0) - UpdateMessage(); -} - -void PluginPlaceholder::SetPluginInfo( - const content::WebPluginInfo& plugin_info) { - plugin_info_ = plugin_info; -} - -const content::WebPluginInfo& PluginPlaceholder::GetPluginInfo() const { - return plugin_info_; -} - -void PluginPlaceholder::SetIdentifier(const std::string& identifier) { - identifier_ = identifier; -} - -WebKit::WebFrame* PluginPlaceholder::GetFrame() { return frame_; } - -const WebKit::WebPluginParams& PluginPlaceholder::GetPluginParams() const { - return plugin_params_; -} - -} // namespace plugins diff --git a/components/plugins/renderer/plugin_placeholder.h b/components/plugins/renderer/plugin_placeholder.h deleted file mode 100644 index 83a13e6..0000000 --- a/components/plugins/renderer/plugin_placeholder.h +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2013 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 COMPONENTS_PLUGINS_RENDERER_PLUGIN_PLACEHOLDER_H_ -#define COMPONENTS_PLUGINS_RENDERER_PLUGIN_PLACEHOLDER_H_ - -#include "components/plugins/renderer/webview_plugin.h" -#include "content/public/common/webplugininfo.h" -#include "content/public/renderer/context_menu_client.h" -#include "content/public/renderer/render_process_observer.h" -#include "content/public/renderer/render_view_observer.h" -#include "third_party/WebKit/public/web/WebPluginParams.h" -#include "webkit/renderer/cpp_bound_class.h" - -namespace content { -struct WebPluginInfo; -} - -namespace plugins { -// Placeholders can be used if a plug-in is missing or not available -// (blocked or disabled). -class PluginPlaceholder : public content::RenderViewObserver, - public webkit_glue::CppBoundClass, - public WebViewPlugin::Delegate { - public: - - 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; } - - 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, - GURL placeholderDataUrl); - - virtual ~PluginPlaceholder(); - - void OnLoadBlockedPlugins(const std::string& identifier); - void OnSetIsPrerendering(bool is_prerendering); - - void SetMessage(const string16& message); - void SetPluginInfo(const content::WebPluginInfo& plugin_info); - const content::WebPluginInfo& GetPluginInfo() const; - void SetIdentifier(const std::string& identifier); - WebKit::WebFrame* GetFrame(); - const WebKit::WebPluginParams& GetPluginParams() const; - bool LoadingAllowed() const { return allow_loading_; } - - // 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(); - - // WebViewPlugin::Delegate method: - virtual void BindWebFrame(WebKit::WebFrame* frame) OVERRIDE; - - private: - // WebViewPlugin::Delegate methods: - virtual void WillDestroyPlugin() OVERRIDE; - virtual void ShowContextMenu(const WebKit::WebMouseEvent&) OVERRIDE; - - // Javascript callbacks: - // All ignore arguments (which are, however, required by caller) and return - // nothing. - - // Load the blocked plugin by calling LoadPlugin(). - void LoadCallback(const webkit_glue::CppArgumentList& args, - webkit_glue::CppVariant* result); - - // Hide the blocked plugin by calling HidePlugin(). - void HideCallback(const webkit_glue::CppArgumentList& args, - webkit_glue::CppVariant* result); - - void DidFinishLoadingCallback(const webkit_glue::CppArgumentList& args, - webkit_glue::CppVariant* result); - - void UpdateMessage(); - - WebKit::WebFrame* frame_; - WebKit::WebPluginParams plugin_params_; - WebViewPlugin* plugin_; - - content::WebPluginInfo plugin_info_; - - string16 message_; - - // 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_; - - bool hidden_; - bool finished_loading_; - std::string identifier_; - - DISALLOW_COPY_AND_ASSIGN(PluginPlaceholder); -}; - -} // namespace plugins - -#endif // COMPONENTS_PLUGINS_RENDERER_PLUGIN_PLACEHOLDER_H_ |