diff options
author | tommycli <tommycli@chromium.org> | 2015-01-21 13:55:36 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-01-21 21:56:45 +0000 |
commit | b20aa015fdfe75dabe8e153309b428bfef867cbd (patch) | |
tree | c941bc92fe9f244ec1dca332c964e810522d4388 /components | |
parent | 277d5afcf3d9001774b23a15e1b8b1a88cc36f16 (diff) | |
download | chromium_src-b20aa015fdfe75dabe8e153309b428bfef867cbd.zip chromium_src-b20aa015fdfe75dabe8e153309b428bfef867cbd.tar.gz chromium_src-b20aa015fdfe75dabe8e153309b428bfef867cbd.tar.bz2 |
Plugin Power Saver: Break LoadablePluginPlaceholder off from PluginPlaceholder
I'm adding lots of plugin loading related functionality to PluginPlaceholder. MobileYoutubePlugin doesn't need that stuff, so I'm breaking that inheritance structure.
BUG=403800
Review URL: https://codereview.chromium.org/803633004
Cr-Commit-Position: refs/heads/master@{#312463}
Diffstat (limited to 'components')
-rw-r--r-- | components/OWNERS | 2 | ||||
-rw-r--r-- | components/plugins.gypi | 2 | ||||
-rw-r--r-- | components/plugins/renderer/BUILD.gn | 2 | ||||
-rw-r--r-- | components/plugins/renderer/loadable_plugin_placeholder.cc | 292 | ||||
-rw-r--r-- | components/plugins/renderer/loadable_plugin_placeholder.h | 125 | ||||
-rw-r--r-- | components/plugins/renderer/plugin_placeholder.cc | 273 | ||||
-rw-r--r-- | components/plugins/renderer/plugin_placeholder.h | 98 |
7 files changed, 430 insertions, 364 deletions
diff --git a/components/OWNERS b/components/OWNERS index fb13bb2..ed7389c 100644 --- a/components/OWNERS +++ b/components/OWNERS @@ -155,6 +155,8 @@ per-file pdf.gypi=jam@chromium.org per-file pdf.gypi=raymes@chromium.org per-file pdf.gypi=thestig@chromium.org +per-file plugins.gypi=bauerb@chromium.org + per-file precache*=bengr@chromium.org per-file precache*=sclittle@chromium.org diff --git a/components/plugins.gypi b/components/plugins.gypi index f03c22b..a052b51 100644 --- a/components/plugins.gypi +++ b/components/plugins.gypi @@ -20,6 +20,8 @@ ], 'sources': [ # Note: sources list duplicated in GN build. + 'plugins/renderer/loadable_plugin_placeholder.cc', + 'plugins/renderer/loadable_plugin_placeholder.h', 'plugins/renderer/plugin_placeholder.cc', 'plugins/renderer/plugin_placeholder.h', 'plugins/renderer/webview_plugin.cc', diff --git a/components/plugins/renderer/BUILD.gn b/components/plugins/renderer/BUILD.gn index c4e2ee3..ef7e8f1 100644 --- a/components/plugins/renderer/BUILD.gn +++ b/components/plugins/renderer/BUILD.gn @@ -4,6 +4,8 @@ static_library("renderer") { sources = [ + "loadable_plugin_placeholder.cc", + "loadable_plugin_placeholder.h", "plugin_placeholder.cc", "plugin_placeholder.h", "webview_plugin.cc", diff --git a/components/plugins/renderer/loadable_plugin_placeholder.cc b/components/plugins/renderer/loadable_plugin_placeholder.cc new file mode 100644 index 0000000..ee9c9b5 --- /dev/null +++ b/components/plugins/renderer/loadable_plugin_placeholder.cc @@ -0,0 +1,292 @@ +// Copyright 2015 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/loadable_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 "content/public/renderer/render_frame.h" +#include "content/public/renderer/render_thread.h" +#include "gin/object_template_builder.h" +#include "third_party/WebKit/public/web/WebElement.h" +#include "third_party/WebKit/public/web/WebInputEvent.h" +#include "third_party/WebKit/public/web/WebLocalFrame.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 base::UserMetricsAction; +using blink::WebElement; +using blink::WebLocalFrame; +using blink::WebMouseEvent; +using blink::WebNode; +using blink::WebPlugin; +using blink::WebPluginContainer; +using blink::WebPluginParams; +using blink::WebScriptSource; +using blink::WebURLRequest; +using content::PluginPowerSaverMode; +using content::RenderThread; + +namespace plugins { + +#if defined(ENABLE_PLUGINS) +void LoadablePluginPlaceholder::BlockForPowerSaverPoster() { + DCHECK(!is_blocked_for_power_saver_poster_); + is_blocked_for_power_saver_poster_ = true; + + render_frame()->RegisterPeripheralPlugin( + GURL(GetPluginParams().url).GetOrigin(), + base::Bind(&LoadablePluginPlaceholder::DisablePowerSaverForInstance, + weak_factory_.GetWeakPtr())); +} +#endif + +LoadablePluginPlaceholder::LoadablePluginPlaceholder( + content::RenderFrame* render_frame, + WebLocalFrame* frame, + const WebPluginParams& params, + const std::string& html_data, + GURL placeholderDataUrl) + : PluginPlaceholder(render_frame, + frame, + params, + html_data, + placeholderDataUrl), + is_blocked_for_background_tab_(false), + is_blocked_for_prerendering_(false), + is_blocked_for_power_saver_poster_(false), + power_saver_mode_(PluginPowerSaverMode::POWER_SAVER_MODE_ESSENTIAL), + allow_loading_(false), + hidden_(false), + finished_loading_(false), + weak_factory_(this) { +} + +LoadablePluginPlaceholder::~LoadablePluginPlaceholder() { +} + +#if defined(ENABLE_PLUGINS) +void LoadablePluginPlaceholder::DisablePowerSaverForInstance() { + power_saver_mode_ = PluginPowerSaverMode::POWER_SAVER_MODE_ESSENTIAL; + if (is_blocked_for_power_saver_poster_) { + is_blocked_for_power_saver_poster_ = false; + if (!LoadingBlocked()) + LoadPlugin(); + } +} +#endif + +gin::ObjectTemplateBuilder LoadablePluginPlaceholder::GetObjectTemplateBuilder( + v8::Isolate* isolate) { + return gin::Wrappable<PluginPlaceholder>::GetObjectTemplateBuilder(isolate) + .SetMethod("load", &LoadablePluginPlaceholder::LoadCallback) + .SetMethod("hide", &LoadablePluginPlaceholder::HideCallback) + .SetMethod("didFinishLoading", + &LoadablePluginPlaceholder::DidFinishLoadingCallback); +} + +void LoadablePluginPlaceholder::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. We + // will be destroyed as soon as V8 garbage collects 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 LoadablePluginPlaceholder::HidePlugin() { + hidden_ = true; + if (!plugin()) + return; + 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); + } + base::TrimWhitespace(width_str, base::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); + } + base::TrimWhitespace(height_str, base::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 LoadablePluginPlaceholder::SetMessage(const base::string16& message) { + message_ = message; + if (finished_loading_) + UpdateMessage(); +} + +void LoadablePluginPlaceholder::UpdateMessage() { + if (!plugin()) + return; + std::string script = + "window.setMessage(" + base::GetQuotedJSONString(message_) + ")"; + plugin()->web_view()->mainFrame()->executeScript( + WebScriptSource(base::UTF8ToUTF16(script))); +} + +void LoadablePluginPlaceholder::ShowContextMenu(const WebMouseEvent& event) { + // Does nothing by default. Will be overridden if a specific browser wants + // a context menu. + return; +} + +void LoadablePluginPlaceholder::WasShown() { + if (is_blocked_for_background_tab_) { + is_blocked_for_background_tab_ = false; + if (!LoadingBlocked()) + LoadPlugin(); + } +} + +void LoadablePluginPlaceholder::OnLoadBlockedPlugins( + const std::string& identifier) { + if (!identifier.empty() && identifier != identifier_) + return; + + RenderThread::Get()->RecordAction(UserMetricsAction("Plugin_Load_UI")); + LoadPlugin(); +} + +void LoadablePluginPlaceholder::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_blocked_for_prerendering_ = false; + if (!LoadingBlocked()) + LoadPlugin(); + } +} + +void LoadablePluginPlaceholder::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 (!plugin()) + 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. + scoped_ptr<content::PluginInstanceThrottler> throttler; +#if defined(ENABLE_PLUGINS) + throttler = content::PluginInstanceThrottler::Get( + render_frame(), GetPluginParams().url, power_saver_mode_); +#endif + WebPlugin* plugin = render_frame()->CreatePlugin( + GetFrame(), plugin_info_, GetPluginParams(), throttler.Pass()); + ReplacePlugin(plugin); +} + +void LoadablePluginPlaceholder::LoadCallback() { + RenderThread::Get()->RecordAction(UserMetricsAction("Plugin_Load_Click")); +#if defined(ENABLE_PLUGINS) + // If the user specifically clicks on the plug-in content's placeholder, + // disable power saver throttling for this instance. + DisablePowerSaverForInstance(); +#endif + LoadPlugin(); +} + +void LoadablePluginPlaceholder::HideCallback() { + RenderThread::Get()->RecordAction(UserMetricsAction("Plugin_Hide_Click")); + HidePlugin(); +} + +void LoadablePluginPlaceholder::DidFinishLoadingCallback() { + finished_loading_ = true; + if (message_.length() > 0) + UpdateMessage(); +} + +void LoadablePluginPlaceholder::SetPluginInfo( + const content::WebPluginInfo& plugin_info) { + plugin_info_ = plugin_info; +} + +const content::WebPluginInfo& LoadablePluginPlaceholder::GetPluginInfo() const { + return plugin_info_; +} + +void LoadablePluginPlaceholder::SetIdentifier(const std::string& identifier) { + identifier_ = identifier; +} + +bool LoadablePluginPlaceholder::LoadingBlocked() const { + DCHECK(allow_loading_); + return is_blocked_for_background_tab_ || is_blocked_for_power_saver_poster_ || + is_blocked_for_prerendering_; +} + +} // namespace plugins diff --git a/components/plugins/renderer/loadable_plugin_placeholder.h b/components/plugins/renderer/loadable_plugin_placeholder.h new file mode 100644 index 0000000..5f3748f --- /dev/null +++ b/components/plugins/renderer/loadable_plugin_placeholder.h @@ -0,0 +1,125 @@ +// Copyright 2015 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_LOADABLE_PLUGIN_PLACEHOLDER_H_ +#define COMPONENTS_PLUGINS_RENDERER_LOADABLE_PLUGIN_PLACEHOLDER_H_ + +#include "base/memory/weak_ptr.h" +#include "components/plugins/renderer/plugin_placeholder.h" +#include "content/public/common/webplugininfo.h" +#include "content/public/renderer/plugin_instance_throttler.h" + +namespace plugins { +// Placeholders can be used if a plug-in is missing or not available +// (blocked or disabled). +class LoadablePluginPlaceholder : public PluginPlaceholder { + public: + void set_blocked_for_background_tab(bool blocked_for_background_tab) { + is_blocked_for_background_tab_ = blocked_for_background_tab; + } + + void set_blocked_for_prerendering(bool blocked_for_prerendering) { + is_blocked_for_prerendering_ = blocked_for_prerendering; + } + +#if defined(ENABLE_PLUGINS) + void set_power_saver_mode(content::PluginPowerSaverMode power_saver_mode) { + power_saver_mode_ = power_saver_mode; + } + + // Defer loading of plug-in, and instead show the Power Saver poster image. + void BlockForPowerSaverPoster(); +#endif + + void set_allow_loading(bool allow_loading) { allow_loading_ = allow_loading; } + + protected: + LoadablePluginPlaceholder(content::RenderFrame* render_frame, + blink::WebLocalFrame* frame, + const blink::WebPluginParams& params, + const std::string& html_data, + GURL placeholderDataUrl); + + ~LoadablePluginPlaceholder() override; + +#if defined(ENABLE_PLUGINS) + void DisablePowerSaverForInstance(); +#endif + + void OnLoadBlockedPlugins(const std::string& identifier); + void OnSetIsPrerendering(bool is_prerendering); + + void SetMessage(const base::string16& message); + void SetPluginInfo(const content::WebPluginInfo& plugin_info); + const content::WebPluginInfo& GetPluginInfo() const; + void SetIdentifier(const std::string& identifier); + bool LoadingAllowed() const { return allow_loading_; } + + // Replace this placeholder with a different plugin (which could be + // a placeholder again). + void ReplacePlugin(blink::WebPlugin* new_plugin); + + // Hide this placeholder. + void HidePlugin(); + + // Load the blocked plugin. + void LoadPlugin(); + + // gin::Wrappable method: + gin::ObjectTemplateBuilder GetObjectTemplateBuilder( + v8::Isolate* isolate) override; + + private: + // WebViewPlugin::Delegate methods: + void ShowContextMenu(const blink::WebMouseEvent&) override; + + // RenderFrameObserver methods: + void WasShown() override; + + // Javascript callbacks: + + // Load the blocked plugin by calling LoadPlugin(). + void LoadCallback(); + + // Hide the blocked plugin by calling HidePlugin(). + void HideCallback(); + + void DidFinishLoadingCallback(); + + void UpdateMessage(); + + bool LoadingBlocked() const; + + content::WebPluginInfo plugin_info_; + + base::string16 message_; + + // True if the plugin load was deferred due to page being a background tab. + // Plugin may be automatically loaded when the page is foregrounded. + bool is_blocked_for_background_tab_; + + // True if the plugin was blocked because the page was being prerendered. + // Plugin may be automatically be loaded when the page is displayed. + bool is_blocked_for_prerendering_; + + // True if the plugin load was deferred due to a Power Saver poster. + bool is_blocked_for_power_saver_poster_; + + // This is independent of deferred plugin load due to a Power Saver poster. + content::PluginPowerSaverMode power_saver_mode_; + + bool allow_loading_; + + bool hidden_; + bool finished_loading_; + std::string identifier_; + + base::WeakPtrFactory<LoadablePluginPlaceholder> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(LoadablePluginPlaceholder); +}; + +} // namespace plugins + +#endif // COMPONENTS_PLUGINS_RENDERER_LOADABLE_PLUGIN_PLACEHOLDER_H_ diff --git a/components/plugins/renderer/plugin_placeholder.cc b/components/plugins/renderer/plugin_placeholder.cc index 563c06b..fbdbc50 100644 --- a/components/plugins/renderer/plugin_placeholder.cc +++ b/components/plugins/renderer/plugin_placeholder.cc @@ -4,59 +4,15 @@ #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_frame.h" -#include "content/public/renderer/render_thread.h" -#include "gin/object_template_builder.h" -#include "third_party/WebKit/public/web/WebDocument.h" -#include "third_party/WebKit/public/web/WebElement.h" -#include "third_party/WebKit/public/web/WebInputEvent.h" -#include "third_party/WebKit/public/web/WebLocalFrame.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 base::UserMetricsAction; -using blink::WebElement; -using blink::WebLocalFrame; -using blink::WebMouseEvent; -using blink::WebNode; -using blink::WebPlugin; -using blink::WebPluginContainer; -using blink::WebPluginParams; -using blink::WebScriptSource; -using blink::WebURLRequest; -using content::PluginPowerSaverMode; -using content::RenderThread; namespace plugins { gin::WrapperInfo PluginPlaceholder::kWrapperInfo = {gin::kEmbedderNativeGin}; -#if defined(ENABLE_PLUGINS) -void PluginPlaceholder::BlockForPowerSaverPoster() { - DCHECK(!is_blocked_for_power_saver_poster_); - is_blocked_for_power_saver_poster_ = true; - - render_frame()->RegisterPeripheralPlugin( - GURL(plugin_params_.url).GetOrigin(), - base::Bind(&PluginPlaceholder::DisablePowerSaverForInstance, - weak_factory_.GetWeakPtr())); -} -#endif - PluginPlaceholder::PluginPlaceholder(content::RenderFrame* render_frame, - WebLocalFrame* frame, - const WebPluginParams& params, + blink::WebLocalFrame* frame, + const blink::WebPluginParams& params, const std::string& html_data, GURL placeholderDataUrl) : content::RenderFrameObserver(render_frame), @@ -65,137 +21,16 @@ PluginPlaceholder::PluginPlaceholder(content::RenderFrame* render_frame, plugin_(WebViewPlugin::Create(this, render_frame->GetWebkitPreferences(), html_data, - placeholderDataUrl)), - is_blocked_for_background_tab_(false), - is_blocked_for_prerendering_(false), - is_blocked_for_power_saver_poster_(false), - power_saver_mode_(PluginPowerSaverMode::POWER_SAVER_MODE_ESSENTIAL), - allow_loading_(false), - hidden_(false), - finished_loading_(false), - weak_factory_(this) { + placeholderDataUrl)) { } PluginPlaceholder::~PluginPlaceholder() {} -#if defined(ENABLE_PLUGINS) -void PluginPlaceholder::DisablePowerSaverForInstance() { - power_saver_mode_ = PluginPowerSaverMode::POWER_SAVER_MODE_ESSENTIAL; - if (is_blocked_for_power_saver_poster_) { - is_blocked_for_power_saver_poster_ = false; - if (!LoadingBlocked()) - LoadPlugin(); - } -} -#endif - -gin::ObjectTemplateBuilder PluginPlaceholder::GetObjectTemplateBuilder( - v8::Isolate* isolate) { - return gin::Wrappable<PluginPlaceholder>::GetObjectTemplateBuilder(isolate) - .SetMethod("load", &PluginPlaceholder::LoadCallback) - .SetMethod("hide", &PluginPlaceholder::HideCallback) - .SetMethod("didFinishLoading", - &PluginPlaceholder::DidFinishLoadingCallback); -} - -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. We - // will be destroyed as soon as V8 garbage collects 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; - if (!plugin_) - return; - 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); - } - base::TrimWhitespace(width_str, base::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); - } - base::TrimWhitespace(height_str, base::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::SetMessage(const base::string16& message) { - message_ = message; - if (finished_loading_) - UpdateMessage(); -} - -void PluginPlaceholder::UpdateMessage() { - if (!plugin_) - return; - std::string script = - "window.setMessage(" + base::GetQuotedJSONString(message_) + ")"; - plugin_->web_view()->mainFrame()->executeScript( - WebScriptSource(base::UTF8ToUTF16(script))); +const blink::WebPluginParams& PluginPlaceholder::GetPluginParams() const { + return plugin_params_; } -void PluginPlaceholder::ShowContextMenu(const WebMouseEvent& event) { +void PluginPlaceholder::ShowContextMenu(const blink::WebMouseEvent& event) { // Does nothing by default. Will be overridden if a specific browser wants // a context menu. return; @@ -205,106 +40,10 @@ void PluginPlaceholder::PluginDestroyed() { plugin_ = NULL; } -void PluginPlaceholder::WasShown() { - if (is_blocked_for_background_tab_) { - is_blocked_for_background_tab_ = false; - if (!LoadingBlocked()) - LoadPlugin(); - } -} - void PluginPlaceholder::OnDestruct() { frame_ = NULL; } -void PluginPlaceholder::OnLoadBlockedPlugins(const std::string& identifier) { - if (!identifier.empty() && identifier != identifier_) - return; - - RenderThread::Get()->RecordAction(UserMetricsAction("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_blocked_for_prerendering_ = false; - if (!LoadingBlocked()) - 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 (!plugin_) - 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. - scoped_ptr<content::PluginInstanceThrottler> throttler; -#if defined(ENABLE_PLUGINS) - throttler = content::PluginInstanceThrottler::Get( - render_frame(), plugin_params_.url, power_saver_mode_); -#endif - WebPlugin* plugin = render_frame()->CreatePlugin( - frame_, plugin_info_, plugin_params_, throttler.Pass()); - ReplacePlugin(plugin); -} - -void PluginPlaceholder::LoadCallback() { - RenderThread::Get()->RecordAction(UserMetricsAction("Plugin_Load_Click")); -// If the user specifically clicks on the plug-in content's placeholder, -// disable power saver throttling for this instance. -#if defined(ENABLE_PLUGINS) - DisablePowerSaverForInstance(); -#endif - LoadPlugin(); -} - -void PluginPlaceholder::HideCallback() { - RenderThread::Get()->RecordAction(UserMetricsAction("Plugin_Hide_Click")); - HidePlugin(); -} - -void PluginPlaceholder::DidFinishLoadingCallback() { - 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; -} - blink::WebLocalFrame* PluginPlaceholder::GetFrame() { return frame_; } -const blink::WebPluginParams& PluginPlaceholder::GetPluginParams() const { - return plugin_params_; -} - -bool PluginPlaceholder::LoadingBlocked() const { - DCHECK(allow_loading_); - return is_blocked_for_background_tab_ || is_blocked_for_power_saver_poster_ || - is_blocked_for_prerendering_; -} - } // namespace plugins diff --git a/components/plugins/renderer/plugin_placeholder.h b/components/plugins/renderer/plugin_placeholder.h index 87d065d..b0f0f4c 100644 --- a/components/plugins/renderer/plugin_placeholder.h +++ b/components/plugins/renderer/plugin_placeholder.h @@ -7,22 +7,12 @@ #include "base/memory/weak_ptr.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/plugin_instance_throttler.h" #include "content/public/renderer/render_frame_observer.h" -#include "content/public/renderer/render_process_observer.h" #include "gin/wrappable.h" #include "third_party/WebKit/public/web/WebPluginParams.h" -namespace content { -class RenderFrame; -struct WebPluginInfo; -} - namespace plugins { -// Placeholders can be used if a plug-in is missing or not available -// (blocked or disabled). + class PluginPlaceholder : public content::RenderFrameObserver, public WebViewPlugin::Delegate, public gin::Wrappable<PluginPlaceholder> { @@ -31,25 +21,6 @@ class PluginPlaceholder : public content::RenderFrameObserver, WebViewPlugin* plugin() { return plugin_; } - void set_blocked_for_background_tab(bool blocked_for_background_tab) { - is_blocked_for_background_tab_ = blocked_for_background_tab; - } - - void set_blocked_for_prerendering(bool blocked_for_prerendering) { - is_blocked_for_prerendering_ = blocked_for_prerendering; - } - -#if defined(ENABLE_PLUGINS) - void set_power_saver_mode(content::PluginPowerSaverMode power_saver_mode) { - power_saver_mode_ = power_saver_mode; - } - - // Defer loading of plug-in, and instead show the Power Saver poster image. - void BlockForPowerSaverPoster(); -#endif - - void set_allow_loading(bool allow_loading) { allow_loading_ = allow_loading; } - protected: // |render_frame| and |frame| are weak pointers. If either one is going away, // our |plugin_| will be destroyed as well and will notify us. @@ -61,34 +32,8 @@ class PluginPlaceholder : public content::RenderFrameObserver, ~PluginPlaceholder() override; -#if defined(ENABLE_PLUGINS) - void DisablePowerSaverForInstance(); -#endif - - void OnLoadBlockedPlugins(const std::string& identifier); - void OnSetIsPrerendering(bool is_prerendering); - - void SetMessage(const base::string16& message); - void SetPluginInfo(const content::WebPluginInfo& plugin_info); - const content::WebPluginInfo& GetPluginInfo() const; - void SetIdentifier(const std::string& identifier); blink::WebLocalFrame* GetFrame(); const blink::WebPluginParams& GetPluginParams() const; - bool LoadingAllowed() const { return allow_loading_; } - - // Replace this placeholder with a different plugin (which could be - // a placeholder again). - void ReplacePlugin(blink::WebPlugin* new_plugin); - - // Hide this placeholder. - void HidePlugin(); - - // Load the blocked plugin. - void LoadPlugin(); - - // gin::Wrappable method: - gin::ObjectTemplateBuilder GetObjectTemplateBuilder( - v8::Isolate* isolate) override; private: // WebViewPlugin::Delegate methods: @@ -96,53 +41,12 @@ class PluginPlaceholder : public content::RenderFrameObserver, void PluginDestroyed() override; // RenderFrameObserver methods: - void WasShown() override; void OnDestruct() override; - // Javascript callbacks: - - // Load the blocked plugin by calling LoadPlugin(). - void LoadCallback(); - - // Hide the blocked plugin by calling HidePlugin(). - void HideCallback(); - - void DidFinishLoadingCallback(); - - void UpdateMessage(); - - bool LoadingBlocked() const; - blink::WebLocalFrame* frame_; blink::WebPluginParams plugin_params_; WebViewPlugin* plugin_; - content::WebPluginInfo plugin_info_; - - base::string16 message_; - - // True if the plugin load was deferred due to page being a background tab. - // Plugin may be automatically loaded when the page is foregrounded. - bool is_blocked_for_background_tab_; - - // True if the plugin was blocked because the page was being prerendered. - // Plugin may be automatically be loaded when the page is displayed. - bool is_blocked_for_prerendering_; - - // True if the plugin load was deferred due to a Power Saver poster. - bool is_blocked_for_power_saver_poster_; - - // This is independent of deferred plugin load due to a Power Saver poster. - content::PluginPowerSaverMode power_saver_mode_; - - bool allow_loading_; - - bool hidden_; - bool finished_loading_; - std::string identifier_; - - base::WeakPtrFactory<PluginPlaceholder> weak_factory_; - DISALLOW_COPY_AND_ASSIGN(PluginPlaceholder); }; |