OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |