Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(433)

Side by Side Diff: components/plugins/renderer/loadable_plugin_placeholder.cc

Issue 866173002: Plugin Power Saver: Add UI Overlay to throttled plugin using placeholder. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/plugins/renderer/loadable_plugin_placeholder.h" 5 #include "components/plugins/renderer/loadable_plugin_placeholder.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
9 #include "base/json/string_escape.h" 9 #include "base/json/string_escape.h"
10 #include "base/strings/string_piece.h" 10 #include "base/strings/string_piece.h"
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 is_blocked_for_power_saver_poster_ = true; 43 is_blocked_for_power_saver_poster_ = true;
44 44
45 render_frame()->RegisterPeripheralPlugin( 45 render_frame()->RegisterPeripheralPlugin(
46 GURL(GetPluginParams().url).GetOrigin(), 46 GURL(GetPluginParams().url).GetOrigin(),
47 base::Bind(&LoadablePluginPlaceholder::DisablePowerSaverForInstance, 47 base::Bind(&LoadablePluginPlaceholder::DisablePowerSaverForInstance,
48 weak_factory_.GetWeakPtr(), 48 weak_factory_.GetWeakPtr(),
49 PluginInstanceThrottler::UNTHROTTLE_METHOD_BY_WHITELIST)); 49 PluginInstanceThrottler::UNTHROTTLE_METHOD_BY_WHITELIST));
50 } 50 }
51 #endif 51 #endif
52 52
53 void LoadablePluginPlaceholder::SetPremadePlugin(
54 blink::WebPlugin* plugin,
55 content::PluginInstanceThrottler* throttler) {
56 DCHECK(!premade_plugin_);
57 DCHECK(!premade_throttler_);
58 premade_plugin_ = plugin;
59 premade_throttler_ = throttler;
60
61 premade_throttler_->AddObserver(this);
62 }
63
53 LoadablePluginPlaceholder::LoadablePluginPlaceholder( 64 LoadablePluginPlaceholder::LoadablePluginPlaceholder(
54 content::RenderFrame* render_frame, 65 content::RenderFrame* render_frame,
55 WebLocalFrame* frame, 66 WebLocalFrame* frame,
56 const WebPluginParams& params, 67 const WebPluginParams& params,
57 const std::string& html_data, 68 const std::string& html_data,
58 GURL placeholderDataUrl) 69 GURL placeholderDataUrl)
59 : PluginPlaceholder(render_frame, 70 : PluginPlaceholder(render_frame,
60 frame, 71 frame,
61 params, 72 params,
62 html_data, 73 html_data,
63 placeholderDataUrl), 74 placeholderDataUrl),
64 is_blocked_for_background_tab_(false), 75 is_blocked_for_background_tab_(false),
65 is_blocked_for_prerendering_(false), 76 is_blocked_for_prerendering_(false),
66 is_blocked_for_power_saver_poster_(false), 77 is_blocked_for_power_saver_poster_(false),
67 power_saver_mode_(PluginPowerSaverMode::POWER_SAVER_MODE_ESSENTIAL), 78 power_saver_mode_(PluginPowerSaverMode::POWER_SAVER_MODE_ESSENTIAL),
79 premade_plugin_(nullptr),
80 premade_throttler_(nullptr),
68 allow_loading_(false), 81 allow_loading_(false),
69 placeholder_was_replaced_(false), 82 placeholder_was_replaced_(false),
70 hidden_(false), 83 hidden_(false),
71 finished_loading_(false), 84 finished_loading_(false),
72 weak_factory_(this) { 85 weak_factory_(this) {
73 } 86 }
74 87
75 LoadablePluginPlaceholder::~LoadablePluginPlaceholder() { 88 LoadablePluginPlaceholder::~LoadablePluginPlaceholder() {
76 #if defined(ENABLE_PLUGINS) 89 #if defined(ENABLE_PLUGINS)
90 if (premade_throttler_)
91 premade_throttler_->RemoveObserver(this);
92
77 if (!placeholder_was_replaced_ && !is_blocked_for_prerendering_ && 93 if (!placeholder_was_replaced_ && !is_blocked_for_prerendering_ &&
78 power_saver_mode_ != PluginPowerSaverMode::POWER_SAVER_MODE_ESSENTIAL) { 94 power_saver_mode_ != PluginPowerSaverMode::POWER_SAVER_MODE_ESSENTIAL) {
79 PluginInstanceThrottler::RecordUnthrottleMethodMetric( 95 PluginInstanceThrottler::RecordUnthrottleMethodMetric(
80 PluginInstanceThrottler::UNTHROTTLE_METHOD_NEVER); 96 PluginInstanceThrottler::UNTHROTTLE_METHOD_NEVER);
81 } 97 }
82 #endif 98 #endif
83 } 99 }
84 100
85 #if defined(ENABLE_PLUGINS) 101 #if defined(ENABLE_PLUGINS)
86 void LoadablePluginPlaceholder::DisablePowerSaverForInstance( 102 void LoadablePluginPlaceholder::DisablePowerSaverForInstance(
87 PluginInstanceThrottler::PowerSaverUnthrottleMethod method) { 103 PluginInstanceThrottler::PowerSaverUnthrottleMethod method) {
88 if (power_saver_mode_ == PluginPowerSaverMode::POWER_SAVER_MODE_ESSENTIAL) 104 if (power_saver_mode_ == PluginPowerSaverMode::POWER_SAVER_MODE_ESSENTIAL)
89 return; 105 return;
90 106
91 power_saver_mode_ = PluginPowerSaverMode::POWER_SAVER_MODE_ESSENTIAL; 107 power_saver_mode_ = PluginPowerSaverMode::POWER_SAVER_MODE_ESSENTIAL;
92 PluginInstanceThrottler::RecordUnthrottleMethodMetric(method); 108 if (premade_throttler_) {
109 premade_throttler_->MarkPluginEssential(method);
110 } else {
111 PluginInstanceThrottler::RecordUnthrottleMethodMetric(method);
112 }
113
93 if (is_blocked_for_power_saver_poster_) { 114 if (is_blocked_for_power_saver_poster_) {
94 is_blocked_for_power_saver_poster_ = false; 115 is_blocked_for_power_saver_poster_ = false;
95 if (!LoadingBlocked()) 116 if (!LoadingBlocked())
96 LoadPlugin(); 117 LoadPlugin();
97 } 118 }
98 } 119 }
99 #endif 120 #endif
100 121
101 gin::ObjectTemplateBuilder LoadablePluginPlaceholder::GetObjectTemplateBuilder( 122 gin::ObjectTemplateBuilder LoadablePluginPlaceholder::GetObjectTemplateBuilder(
102 v8::Isolate* isolate) { 123 v8::Isolate* isolate) {
103 return gin::Wrappable<PluginPlaceholder>::GetObjectTemplateBuilder(isolate) 124 return gin::Wrappable<PluginPlaceholder>::GetObjectTemplateBuilder(isolate)
104 .SetMethod("load", &LoadablePluginPlaceholder::LoadCallback) 125 .SetMethod("load", &LoadablePluginPlaceholder::LoadCallback)
105 .SetMethod("hide", &LoadablePluginPlaceholder::HideCallback) 126 .SetMethod("hide", &LoadablePluginPlaceholder::HideCallback)
106 .SetMethod("didFinishLoading", 127 .SetMethod("didFinishLoading",
107 &LoadablePluginPlaceholder::DidFinishLoadingCallback); 128 &LoadablePluginPlaceholder::DidFinishLoadingCallback);
108 } 129 }
109 130
110 void LoadablePluginPlaceholder::ReplacePlugin(WebPlugin* new_plugin) { 131 void LoadablePluginPlaceholder::ReplacePlugin(WebPlugin* new_plugin) {
111 CHECK(plugin()); 132 CHECK(plugin());
112 if (!new_plugin) 133 if (!new_plugin)
113 return; 134 return;
114 WebPluginContainer* container = plugin()->container(); 135 WebPluginContainer* container = plugin()->container();
115 // Set the new plug-in on the container before initializing it. 136 // Set the new plug-in on the container before initializing it.
116 container->setPlugin(new_plugin); 137 container->setPlugin(new_plugin);
117 // Save the element in case the plug-in is removed from the page during 138 // Save the element in case the plug-in is removed from the page during
118 // initialization. 139 // initialization.
119 WebElement element = container->element(); 140 WebElement element = container->element();
120 if (!new_plugin->initialize(container)) { 141 if (new_plugin != premade_plugin_ && !new_plugin->initialize(container)) {
121 // We couldn't initialize the new plug-in. Restore the old one and abort. 142 // We couldn't initialize the new plug-in. Restore the old one and abort.
122 container->setPlugin(plugin()); 143 container->setPlugin(plugin());
123 return; 144 return;
124 } 145 }
125 146
126 // The plug-in has been removed from the page. Destroy the old plug-in. We 147 // The plug-in has been removed from the page. Destroy the old plug-in. We
127 // will be destroyed as soon as V8 garbage collects us. 148 // will be destroyed as soon as V8 garbage collects us.
128 if (!element.pluginContainer()) { 149 if (!element.pluginContainer()) {
129 plugin()->destroy(); 150 plugin()->destroy();
130 return; 151 return;
131 } 152 }
132 153
154 placeholder_was_replaced_ = true;
155
133 // During initialization, the new plug-in might have replaced itself in turn 156 // During initialization, the new plug-in might have replaced itself in turn
134 // with another plug-in. Make sure not to use the passed in |new_plugin| after 157 // with another plug-in. Make sure not to use the passed in |new_plugin| after
135 // this point. 158 // this point.
136 new_plugin = container->plugin(); 159 new_plugin = container->plugin();
137 160
138 plugin()->RestoreTitleText(); 161 plugin()->RestoreTitleText();
139 container->invalidate(); 162 container->invalidate();
140 container->reportGeometry(); 163 container->reportGeometry();
141 plugin()->ReplayReceivedData(new_plugin); 164 plugin()->ReplayReceivedData(new_plugin);
142 plugin()->destroy(); 165 plugin()->destroy();
143
144 placeholder_was_replaced_ = true;
145 } 166 }
146 167
147 void LoadablePluginPlaceholder::HidePlugin() { 168 void LoadablePluginPlaceholder::HidePlugin() {
148 hidden_ = true; 169 hidden_ = true;
149 if (!plugin()) 170 if (!plugin())
150 return; 171 return;
151 WebPluginContainer* container = plugin()->container(); 172 WebPluginContainer* container = plugin()->container();
152 WebElement element = container->element(); 173 WebElement element = container->element();
153 element.setAttribute("style", "display: none;"); 174 element.setAttribute("style", "display: none;");
154 // If we have a width and height, search for a parent (often <div>) with the 175 // If we have a width and height, search for a parent (often <div>) with the
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
200 221
201 void LoadablePluginPlaceholder::UpdateMessage() { 222 void LoadablePluginPlaceholder::UpdateMessage() {
202 if (!plugin()) 223 if (!plugin())
203 return; 224 return;
204 std::string script = 225 std::string script =
205 "window.setMessage(" + base::GetQuotedJSONString(message_) + ")"; 226 "window.setMessage(" + base::GetQuotedJSONString(message_) + ")";
206 plugin()->web_view()->mainFrame()->executeScript( 227 plugin()->web_view()->mainFrame()->executeScript(
207 WebScriptSource(base::UTF8ToUTF16(script))); 228 WebScriptSource(base::UTF8ToUTF16(script)));
208 } 229 }
209 230
210 void LoadablePluginPlaceholder::ShowContextMenu(const WebMouseEvent& event) { 231 void LoadablePluginPlaceholder::PluginDestroyed() {
211 // Does nothing by default. Will be overridden if a specific browser wants 232 // Since the premade plugin has been detached from the container, it will not
212 // a context menu. 233 // be automatically destroyed along with the page.
213 return; 234 if (!placeholder_was_replaced_ && premade_plugin_) {
235 premade_plugin_->destroy();
236 premade_plugin_ = nullptr;
237 premade_throttler_ = nullptr;
238 }
239
240 PluginPlaceholder::PluginDestroyed();
214 } 241 }
215 242
216 void LoadablePluginPlaceholder::WasShown() { 243 void LoadablePluginPlaceholder::WasShown() {
217 if (is_blocked_for_background_tab_) { 244 if (is_blocked_for_background_tab_) {
218 is_blocked_for_background_tab_ = false; 245 is_blocked_for_background_tab_ = false;
219 if (!LoadingBlocked()) 246 if (!LoadingBlocked())
220 LoadPlugin(); 247 LoadPlugin();
221 } 248 }
222 } 249 }
223 250
251 void LoadablePluginPlaceholder::OnThrottleStateChange() {
252 DCHECK(premade_plugin_);
253 DCHECK(premade_throttler_);
254 if (!premade_throttler_->IsThrottled()) {
255 // Premade plugin has been unthrottled externally (by audio playback, etc.).
256 LoadPlugin();
257 }
258 }
259
224 void LoadablePluginPlaceholder::OnLoadBlockedPlugins( 260 void LoadablePluginPlaceholder::OnLoadBlockedPlugins(
225 const std::string& identifier) { 261 const std::string& identifier) {
226 if (!identifier.empty() && identifier != identifier_) 262 if (!identifier.empty() && identifier != identifier_)
227 return; 263 return;
228 264
229 RenderThread::Get()->RecordAction(UserMetricsAction("Plugin_Load_UI")); 265 RenderThread::Get()->RecordAction(UserMetricsAction("Plugin_Load_UI"));
230 LoadPlugin(); 266 LoadPlugin();
231 } 267 }
232 268
233 void LoadablePluginPlaceholder::OnSetIsPrerendering(bool is_prerendering) { 269 void LoadablePluginPlaceholder::OnSetIsPrerendering(bool is_prerendering) {
(...skipping 12 matching lines...) Expand all
246 // event propagation changes between "close" vs. "click-to-play". 282 // event propagation changes between "close" vs. "click-to-play".
247 if (hidden_) 283 if (hidden_)
248 return; 284 return;
249 if (!plugin()) 285 if (!plugin())
250 return; 286 return;
251 if (!allow_loading_) { 287 if (!allow_loading_) {
252 NOTREACHED(); 288 NOTREACHED();
253 return; 289 return;
254 } 290 }
255 291
256 // TODO(mmenke): In the case of prerendering, feed into 292 if (premade_plugin_) {
257 // ChromeContentRendererClient::CreatePlugin instead, to 293 // Show the (presumably hidden) premade plugin again.
258 // reduce the chance of future regressions. 294 premade_plugin_->updateVisibility(true);
259 scoped_ptr<PluginInstanceThrottler> throttler; 295
296 ReplacePlugin(premade_plugin_);
297
298 premade_throttler_->RemoveObserver(this);
299 premade_plugin_ = nullptr;
300 premade_throttler_ = nullptr;
301 } else {
302 // TODO(mmenke): In the case of prerendering, feed into
303 // ChromeContentRendererClient::CreatePlugin instead, to
304 // reduce the chance of future regressions.
305 scoped_ptr<PluginInstanceThrottler> throttler;
260 #if defined(ENABLE_PLUGINS) 306 #if defined(ENABLE_PLUGINS)
261 throttler = PluginInstanceThrottler::Get( 307 throttler = PluginInstanceThrottler::Get(
262 render_frame(), GetPluginParams().url, power_saver_mode_); 308 render_frame(), GetPluginParams().url, power_saver_mode_);
263 #endif 309 #endif
264 WebPlugin* plugin = render_frame()->CreatePlugin( 310 WebPlugin* plugin = render_frame()->CreatePlugin(
265 GetFrame(), plugin_info_, GetPluginParams(), throttler.Pass()); 311 GetFrame(), plugin_info_, GetPluginParams(), throttler.Pass());
266 ReplacePlugin(plugin); 312
313 ReplacePlugin(plugin);
314 }
267 } 315 }
268 316
269 void LoadablePluginPlaceholder::LoadCallback() { 317 void LoadablePluginPlaceholder::LoadCallback() {
270 RenderThread::Get()->RecordAction(UserMetricsAction("Plugin_Load_Click")); 318 RenderThread::Get()->RecordAction(UserMetricsAction("Plugin_Load_Click"));
271 #if defined(ENABLE_PLUGINS) 319 #if defined(ENABLE_PLUGINS)
272 // If the user specifically clicks on the plug-in content's placeholder, 320 // If the user specifically clicks on the plug-in content's placeholder,
273 // disable power saver throttling for this instance. 321 // disable power saver throttling for this instance.
274 DisablePowerSaverForInstance( 322 DisablePowerSaverForInstance(
275 PluginInstanceThrottler::UNTHROTTLE_METHOD_BY_CLICK); 323 PluginInstanceThrottler::UNTHROTTLE_METHOD_BY_CLICK);
276 #endif 324 #endif
277 LoadPlugin(); 325 LoadPlugin();
278 } 326 }
279 327
280 void LoadablePluginPlaceholder::HideCallback() { 328 void LoadablePluginPlaceholder::HideCallback() {
281 RenderThread::Get()->RecordAction(UserMetricsAction("Plugin_Hide_Click")); 329 RenderThread::Get()->RecordAction(UserMetricsAction("Plugin_Hide_Click"));
282 HidePlugin(); 330 HidePlugin();
283 } 331 }
284 332
285 void LoadablePluginPlaceholder::DidFinishLoadingCallback() { 333 void LoadablePluginPlaceholder::DidFinishLoadingCallback() {
286 finished_loading_ = true; 334 finished_loading_ = true;
287 if (message_.length() > 0) 335 if (message_.length() > 0)
288 UpdateMessage(); 336 UpdateMessage();
337
338 // Wait for the placeholder to finish loading to hide the premade plugin.
339 // This is necessary to prevent a flicker.
340 if (premade_plugin_ && !placeholder_was_replaced_) {
341 premade_plugin_->updateVisibility(false);
342 }
289 } 343 }
290 344
291 void LoadablePluginPlaceholder::SetPluginInfo( 345 void LoadablePluginPlaceholder::SetPluginInfo(
292 const content::WebPluginInfo& plugin_info) { 346 const content::WebPluginInfo& plugin_info) {
293 plugin_info_ = plugin_info; 347 plugin_info_ = plugin_info;
294 } 348 }
295 349
296 const content::WebPluginInfo& LoadablePluginPlaceholder::GetPluginInfo() const { 350 const content::WebPluginInfo& LoadablePluginPlaceholder::GetPluginInfo() const {
297 return plugin_info_; 351 return plugin_info_;
298 } 352 }
299 353
300 void LoadablePluginPlaceholder::SetIdentifier(const std::string& identifier) { 354 void LoadablePluginPlaceholder::SetIdentifier(const std::string& identifier) {
301 identifier_ = identifier; 355 identifier_ = identifier;
302 } 356 }
303 357
304 bool LoadablePluginPlaceholder::LoadingBlocked() const { 358 bool LoadablePluginPlaceholder::LoadingBlocked() const {
305 DCHECK(allow_loading_); 359 DCHECK(allow_loading_);
306 return is_blocked_for_background_tab_ || is_blocked_for_power_saver_poster_ || 360 return is_blocked_for_background_tab_ || is_blocked_for_power_saver_poster_ ||
307 is_blocked_for_prerendering_; 361 is_blocked_for_prerendering_;
308 } 362 }
309 363
310 } // namespace plugins 364 } // namespace plugins
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698