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

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

Powered by Google App Engine
This is Rietveld 408576698