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

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

Issue 1161923004: Reland: Plugin Placeholders: Refactor for platforms that don't support plugins (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: A versio that removes gin Wrappable subclassing Created 5 years, 6 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/command_line.h" 9 #include "base/command_line.h"
10 #include "base/json/string_escape.h" 10 #include "base/json/string_escape.h"
11 #include "base/strings/string_piece.h" 11 #include "base/strings/string_piece.h"
12 #include "base/strings/string_util.h"
13 #include "base/strings/utf_string_conversions.h" 12 #include "base/strings/utf_string_conversions.h"
14 #include "base/values.h" 13 #include "base/values.h"
15 #include "content/public/child/v8_value_converter.h" 14 #include "content/public/child/v8_value_converter.h"
16 #include "content/public/common/content_switches.h" 15 #include "content/public/common/content_switches.h"
17 #include "content/public/renderer/render_frame.h" 16 #include "content/public/renderer/render_frame.h"
18 #include "content/public/renderer/render_thread.h" 17 #include "content/public/renderer/render_thread.h"
19 #include "gin/handle.h" 18 #include "gin/handle.h"
20 #include "gin/object_template_builder.h" 19 #include "gin/object_template_builder.h"
21 #include "third_party/WebKit/public/web/WebDOMMessageEvent.h" 20 #include "third_party/WebKit/public/web/WebDOMMessageEvent.h"
22 #include "third_party/WebKit/public/web/WebDocument.h" 21 #include "third_party/WebKit/public/web/WebDocument.h"
23 #include "third_party/WebKit/public/web/WebElement.h" 22 #include "third_party/WebKit/public/web/WebElement.h"
24 #include "third_party/WebKit/public/web/WebInputEvent.h" 23 #include "third_party/WebKit/public/web/WebInputEvent.h"
25 #include "third_party/WebKit/public/web/WebKit.h" 24 #include "third_party/WebKit/public/web/WebKit.h"
26 #include "third_party/WebKit/public/web/WebLocalFrame.h" 25 #include "third_party/WebKit/public/web/WebLocalFrame.h"
27 #include "third_party/WebKit/public/web/WebPluginContainer.h" 26 #include "third_party/WebKit/public/web/WebPluginContainer.h"
28 #include "third_party/WebKit/public/web/WebScriptSource.h" 27 #include "third_party/WebKit/public/web/WebScriptSource.h"
29 #include "third_party/WebKit/public/web/WebSerializedScriptValue.h" 28 #include "third_party/WebKit/public/web/WebSerializedScriptValue.h"
30 #include "third_party/WebKit/public/web/WebView.h" 29 #include "third_party/WebKit/public/web/WebView.h"
31 #include "third_party/re2/re2/re2.h"
32 30
33 using base::UserMetricsAction; 31 using base::UserMetricsAction;
34 using blink::WebElement;
35 using blink::WebLocalFrame;
36 using blink::WebMouseEvent;
37 using blink::WebNode;
38 using blink::WebPlugin;
39 using blink::WebPluginContainer;
40 using blink::WebPluginParams;
41 using blink::WebScriptSource;
42 using blink::WebURLRequest;
43 using content::PluginInstanceThrottler; 32 using content::PluginInstanceThrottler;
44 using content::RenderThread; 33 using content::RenderThread;
45 34
46 namespace plugins { 35 namespace plugins {
47 36
48 #if defined(ENABLE_PLUGINS)
49 void LoadablePluginPlaceholder::BlockForPowerSaverPoster() { 37 void LoadablePluginPlaceholder::BlockForPowerSaverPoster() {
50 DCHECK(!is_blocked_for_power_saver_poster_); 38 DCHECK(!is_blocked_for_power_saver_poster_);
51 is_blocked_for_power_saver_poster_ = true; 39 is_blocked_for_power_saver_poster_ = true;
52 40
53 render_frame()->RegisterPeripheralPlugin( 41 render_frame()->RegisterPeripheralPlugin(
54 GURL(GetPluginParams().url).GetOrigin(), 42 GURL(GetPluginParams().url).GetOrigin(),
55 base::Bind(&LoadablePluginPlaceholder::MarkPluginEssential, 43 base::Bind(&LoadablePluginPlaceholder::MarkPluginEssential,
56 weak_factory_.GetWeakPtr(), 44 weak_factory_.GetWeakPtr(),
57 PluginInstanceThrottler::UNTHROTTLE_METHOD_BY_WHITELIST)); 45 PluginInstanceThrottler::UNTHROTTLE_METHOD_BY_WHITELIST));
58 } 46 }
59 47
60 void LoadablePluginPlaceholder::SetPremadePlugin( 48 void LoadablePluginPlaceholder::SetPremadePlugin(
61 content::PluginInstanceThrottler* throttler) { 49 content::PluginInstanceThrottler* throttler) {
62 DCHECK(throttler); 50 DCHECK(throttler);
63 DCHECK(!premade_throttler_); 51 DCHECK(!premade_throttler_);
64 premade_throttler_ = throttler; 52 premade_throttler_ = throttler;
65 } 53 }
66 #endif
67 54
68 LoadablePluginPlaceholder::LoadablePluginPlaceholder( 55 LoadablePluginPlaceholder::LoadablePluginPlaceholder(
69 content::RenderFrame* render_frame, 56 content::RenderFrame* render_frame,
70 WebLocalFrame* frame, 57 blink::WebLocalFrame* frame,
71 const WebPluginParams& params, 58 const blink::WebPluginParams& params,
72 const std::string& html_data, 59 const std::string& html_data)
73 GURL placeholderDataUrl) 60 : PluginPlaceholderBase(render_frame, frame, params, html_data),
74 : PluginPlaceholder(render_frame,
75 frame,
76 params,
77 html_data,
78 placeholderDataUrl),
79 is_blocked_for_background_tab_(false), 61 is_blocked_for_background_tab_(false),
80 is_blocked_for_prerendering_(false), 62 is_blocked_for_prerendering_(false),
81 is_blocked_for_power_saver_poster_(false), 63 is_blocked_for_power_saver_poster_(false),
82 power_saver_enabled_(false), 64 power_saver_enabled_(false),
83 premade_throttler_(nullptr), 65 premade_throttler_(nullptr),
84 allow_loading_(false), 66 allow_loading_(true),
85 hidden_(false),
86 finished_loading_(false), 67 finished_loading_(false),
87 weak_factory_(this) { 68 weak_factory_(this) {
88 } 69 }
89 70
90 LoadablePluginPlaceholder::~LoadablePluginPlaceholder() { 71 LoadablePluginPlaceholder::~LoadablePluginPlaceholder() {
91 } 72 }
92 73
93 #if defined(ENABLE_PLUGINS)
94 void LoadablePluginPlaceholder::MarkPluginEssential( 74 void LoadablePluginPlaceholder::MarkPluginEssential(
95 PluginInstanceThrottler::PowerSaverUnthrottleMethod method) { 75 PluginInstanceThrottler::PowerSaverUnthrottleMethod method) {
96 if (!power_saver_enabled_) 76 if (!power_saver_enabled_)
97 return; 77 return;
98 78
99 power_saver_enabled_ = false; 79 power_saver_enabled_ = false;
100 80
101 if (premade_throttler_) 81 if (premade_throttler_)
102 premade_throttler_->MarkPluginEssential(method); 82 premade_throttler_->MarkPluginEssential(method);
103 else 83 else
104 PluginInstanceThrottler::RecordUnthrottleMethodMetric(method); 84 PluginInstanceThrottler::RecordUnthrottleMethodMetric(method);
105 85
106 if (is_blocked_for_power_saver_poster_) { 86 if (is_blocked_for_power_saver_poster_) {
107 is_blocked_for_power_saver_poster_ = false; 87 is_blocked_for_power_saver_poster_ = false;
108 if (!LoadingBlocked()) 88 if (!LoadingBlocked())
109 LoadPlugin(); 89 LoadPlugin();
110 } 90 }
111 } 91 }
112 #endif
113 92
114 void LoadablePluginPlaceholder::BindWebFrame(blink::WebFrame* frame) { 93 void LoadablePluginPlaceholder::ReplacePlugin(blink::WebPlugin* new_plugin) {
115 v8::Isolate* isolate = blink::mainThreadIsolate();
116 v8::HandleScope handle_scope(isolate);
117 v8::Local<v8::Context> context = frame->mainWorldScriptContext();
118 DCHECK(!context.IsEmpty());
119
120 v8::Context::Scope context_scope(context);
121 v8::Local<v8::Object> global = context->Global();
122 global->Set(gin::StringToV8(isolate, "plugin"),
123 gin::CreateHandle(isolate, this).ToV8());
124 }
125
126 gin::ObjectTemplateBuilder LoadablePluginPlaceholder::GetObjectTemplateBuilder(
127 v8::Isolate* isolate) {
128 return gin::Wrappable<PluginPlaceholder>::GetObjectTemplateBuilder(isolate)
129 .SetMethod("load", &LoadablePluginPlaceholder::LoadCallback)
130 .SetMethod("hide", &LoadablePluginPlaceholder::HideCallback)
131 .SetMethod("didFinishLoading",
132 &LoadablePluginPlaceholder::DidFinishLoadingCallback);
133 }
134
135 void LoadablePluginPlaceholder::ReplacePlugin(WebPlugin* new_plugin) {
136 CHECK(plugin()); 94 CHECK(plugin());
137 if (!new_plugin) 95 if (!new_plugin)
138 return; 96 return;
139 WebPluginContainer* container = plugin()->container(); 97 blink::WebPluginContainer* container = plugin()->container();
140 // Set the new plugin on the container before initializing it. 98 // Set the new plugin on the container before initializing it.
141 container->setPlugin(new_plugin); 99 container->setPlugin(new_plugin);
142 // Save the element in case the plugin is removed from the page during 100 // Save the element in case the plugin is removed from the page during
143 // initialization. 101 // initialization.
144 WebElement element = container->element(); 102 blink::WebElement element = container->element();
145 bool plugin_needs_initialization = 103 bool plugin_needs_initialization =
146 !premade_throttler_ || new_plugin != premade_throttler_->GetWebPlugin(); 104 !premade_throttler_ || new_plugin != premade_throttler_->GetWebPlugin();
147 if (plugin_needs_initialization && !new_plugin->initialize(container)) { 105 if (plugin_needs_initialization && !new_plugin->initialize(container)) {
148 // We couldn't initialize the new plugin. Restore the old one and abort. 106 // We couldn't initialize the new plugin. Restore the old one and abort.
149 container->setPlugin(plugin()); 107 container->setPlugin(plugin());
150 return; 108 return;
151 } 109 }
152 110
153 // The plugin has been removed from the page. Destroy the old plugin. We 111 // The plugin has been removed from the page. Destroy the old plugin. We
154 // will be destroyed as soon as V8 garbage collects us. 112 // will be destroyed as soon as V8 garbage collects us.
155 if (!element.pluginContainer()) { 113 if (!element.pluginContainer()) {
156 plugin()->destroy(); 114 plugin()->destroy();
157 return; 115 return;
158 } 116 }
159 117
160 // During initialization, the new plugin might have replaced itself in turn 118 // During initialization, the new plugin might have replaced itself in turn
161 // with another plugin. Make sure not to use the passed in |new_plugin| after 119 // with another plugin. Make sure not to use the passed in |new_plugin| after
162 // this point. 120 // this point.
163 new_plugin = container->plugin(); 121 new_plugin = container->plugin();
164 122
165 plugin()->RestoreTitleText(); 123 plugin()->RestoreTitleText();
166 container->invalidate(); 124 container->invalidate();
167 container->reportGeometry(); 125 container->reportGeometry();
168 plugin()->ReplayReceivedData(new_plugin); 126 plugin()->ReplayReceivedData(new_plugin);
169 plugin()->destroy(); 127 plugin()->destroy();
170 } 128 }
171 129
172 void LoadablePluginPlaceholder::HidePlugin() {
173 hidden_ = true;
174 if (!plugin())
175 return;
176 WebPluginContainer* container = plugin()->container();
177 WebElement element = container->element();
178 element.setAttribute("style", "display: none;");
179 // If we have a width and height, search for a parent (often <div>) with the
180 // same dimensions. If we find such a parent, hide that as well.
181 // This makes much more uncovered page content usable (including clickable)
182 // as opposed to merely visible.
183 // TODO(cevans) -- it's a foul heuristic but we're going to tolerate it for
184 // now for these reasons:
185 // 1) Makes the user experience better.
186 // 2) Foulness is encapsulated within this single function.
187 // 3) Confidence in no fasle positives.
188 // 4) Seems to have a good / low false negative rate at this time.
189 if (element.hasAttribute("width") && element.hasAttribute("height")) {
190 std::string width_str("width:[\\s]*");
191 width_str += element.getAttribute("width").utf8().data();
192 if (EndsWith(width_str, "px", false)) {
193 width_str = width_str.substr(0, width_str.length() - 2);
194 }
195 base::TrimWhitespace(width_str, base::TRIM_TRAILING, &width_str);
196 width_str += "[\\s]*px";
197 std::string height_str("height:[\\s]*");
198 height_str += element.getAttribute("height").utf8().data();
199 if (EndsWith(height_str, "px", false)) {
200 height_str = height_str.substr(0, height_str.length() - 2);
201 }
202 base::TrimWhitespace(height_str, base::TRIM_TRAILING, &height_str);
203 height_str += "[\\s]*px";
204 WebNode parent = element;
205 while (!parent.parentNode().isNull()) {
206 parent = parent.parentNode();
207 if (!parent.isElementNode())
208 continue;
209 element = parent.toConst<WebElement>();
210 if (element.hasAttribute("style")) {
211 std::string style_str = element.getAttribute("style").utf8();
212 if (RE2::PartialMatch(style_str, width_str) &&
213 RE2::PartialMatch(style_str, height_str))
214 element.setAttribute("style", "display: none;");
215 }
216 }
217 }
218 }
219
220 void LoadablePluginPlaceholder::SetMessage(const base::string16& message) { 130 void LoadablePluginPlaceholder::SetMessage(const base::string16& message) {
221 message_ = message; 131 message_ = message;
222 if (finished_loading_) 132 if (finished_loading_)
223 UpdateMessage(); 133 UpdateMessage();
224 } 134 }
225 135
226 void LoadablePluginPlaceholder::UpdateMessage() { 136 void LoadablePluginPlaceholder::UpdateMessage() {
227 if (!plugin()) 137 if (!plugin())
228 return; 138 return;
229 std::string script = 139 std::string script =
230 "window.setMessage(" + base::GetQuotedJSONString(message_) + ")"; 140 "window.setMessage(" + base::GetQuotedJSONString(message_) + ")";
231 plugin()->web_view()->mainFrame()->executeScript( 141 plugin()->web_view()->mainFrame()->executeScript(
232 WebScriptSource(base::UTF8ToUTF16(script))); 142 blink::WebScriptSource(base::UTF8ToUTF16(script)));
233 } 143 }
234 144
235 void LoadablePluginPlaceholder::PluginDestroyed() { 145 void LoadablePluginPlaceholder::PluginDestroyed() {
236 #if defined(ENABLE_PLUGINS)
237 if (power_saver_enabled_) { 146 if (power_saver_enabled_) {
238 if (premade_throttler_) { 147 if (premade_throttler_) {
239 // Since the premade plugin has been detached from the container, it will 148 // Since the premade plugin has been detached from the container, it will
240 // not be automatically destroyed along with the page. 149 // not be automatically destroyed along with the page.
241 premade_throttler_->GetWebPlugin()->destroy(); 150 premade_throttler_->GetWebPlugin()->destroy();
242 premade_throttler_ = nullptr; 151 premade_throttler_ = nullptr;
243 } else if (is_blocked_for_power_saver_poster_) { 152 } else if (is_blocked_for_power_saver_poster_) {
244 // Record the NEVER unthrottle count only if there is no throttler. 153 // Record the NEVER unthrottle count only if there is no throttler.
245 PluginInstanceThrottler::RecordUnthrottleMethodMetric( 154 PluginInstanceThrottler::RecordUnthrottleMethodMetric(
246 PluginInstanceThrottler::UNTHROTTLE_METHOD_NEVER); 155 PluginInstanceThrottler::UNTHROTTLE_METHOD_NEVER);
247 } 156 }
248 157
249 // Prevent processing subsequent calls to MarkPluginEssential. 158 // Prevent processing subsequent calls to MarkPluginEssential.
250 power_saver_enabled_ = false; 159 power_saver_enabled_ = false;
251 } 160 }
252 #endif
253 161
254 PluginPlaceholder::PluginDestroyed(); 162 PluginPlaceholderBase::PluginDestroyed();
255 } 163 }
256 164
257 v8::Local<v8::Object> LoadablePluginPlaceholder::GetV8ScriptableObject( 165 v8::Local<v8::Object> LoadablePluginPlaceholder::GetV8ScriptableObject(
258 v8::Isolate* isolate) const { 166 v8::Isolate* isolate) const {
259 #if defined(ENABLE_PLUGINS)
260 // Pass through JavaScript access to the underlying throttled plugin. 167 // Pass through JavaScript access to the underlying throttled plugin.
261 if (premade_throttler_ && premade_throttler_->GetWebPlugin()) { 168 if (premade_throttler_ && premade_throttler_->GetWebPlugin()) {
262 return premade_throttler_->GetWebPlugin()->v8ScriptableObject(isolate); 169 return premade_throttler_->GetWebPlugin()->v8ScriptableObject(isolate);
263 } 170 }
264 #endif
265 return v8::Local<v8::Object>(); 171 return v8::Local<v8::Object>();
266 } 172 }
267 173
268 void LoadablePluginPlaceholder::WasShown() { 174 void LoadablePluginPlaceholder::WasShown() {
269 if (is_blocked_for_background_tab_) { 175 if (is_blocked_for_background_tab_) {
270 is_blocked_for_background_tab_ = false; 176 is_blocked_for_background_tab_ = false;
271 if (!LoadingBlocked()) 177 if (!LoadingBlocked())
272 LoadPlugin(); 178 LoadPlugin();
273 } 179 }
274 } 180 }
(...skipping 14 matching lines...) Expand all
289 if (is_blocked_for_prerendering_) { 195 if (is_blocked_for_prerendering_) {
290 is_blocked_for_prerendering_ = false; 196 is_blocked_for_prerendering_ = false;
291 if (!LoadingBlocked()) 197 if (!LoadingBlocked())
292 LoadPlugin(); 198 LoadPlugin();
293 } 199 }
294 } 200 }
295 201
296 void LoadablePluginPlaceholder::LoadPlugin() { 202 void LoadablePluginPlaceholder::LoadPlugin() {
297 // This is not strictly necessary but is an important defense in case the 203 // This is not strictly necessary but is an important defense in case the
298 // event propagation changes between "close" vs. "click-to-play". 204 // event propagation changes between "close" vs. "click-to-play".
299 if (hidden_) 205 if (hidden())
300 return; 206 return;
301 if (!plugin()) 207 if (!plugin())
302 return; 208 return;
303 if (!allow_loading_) { 209 if (!allow_loading_) {
304 NOTREACHED(); 210 NOTREACHED();
305 return; 211 return;
306 } 212 }
307 213
308 if (premade_throttler_) { 214 if (premade_throttler_) {
309 premade_throttler_->SetHiddenForPlaceholder(false /* hidden */); 215 premade_throttler_->SetHiddenForPlaceholder(false /* hidden */);
310 ReplacePlugin(premade_throttler_->GetWebPlugin()); 216 ReplacePlugin(premade_throttler_->GetWebPlugin());
311 premade_throttler_ = nullptr; 217 premade_throttler_ = nullptr;
312 } else { 218 } else {
313 ReplacePlugin(CreatePlugin()); 219 ReplacePlugin(CreatePlugin());
314 } 220 }
315 } 221 }
316 222
317 void LoadablePluginPlaceholder::LoadCallback() { 223 void LoadablePluginPlaceholder::LoadCallback() {
318 RenderThread::Get()->RecordAction(UserMetricsAction("Plugin_Load_Click")); 224 RenderThread::Get()->RecordAction(UserMetricsAction("Plugin_Load_Click"));
319 #if defined(ENABLE_PLUGINS)
320 // If the user specifically clicks on the plugin content's placeholder, 225 // If the user specifically clicks on the plugin content's placeholder,
321 // disable power saver throttling for this instance. 226 // disable power saver throttling for this instance.
322 MarkPluginEssential(PluginInstanceThrottler::UNTHROTTLE_METHOD_BY_CLICK); 227 MarkPluginEssential(PluginInstanceThrottler::UNTHROTTLE_METHOD_BY_CLICK);
323 #endif
324 LoadPlugin(); 228 LoadPlugin();
325 } 229 }
326 230
327 void LoadablePluginPlaceholder::HideCallback() {
328 RenderThread::Get()->RecordAction(UserMetricsAction("Plugin_Hide_Click"));
329 HidePlugin();
330 }
331
332 void LoadablePluginPlaceholder::DidFinishLoadingCallback() { 231 void LoadablePluginPlaceholder::DidFinishLoadingCallback() {
333 finished_loading_ = true; 232 finished_loading_ = true;
334 if (message_.length() > 0) 233 if (message_.length() > 0)
335 UpdateMessage(); 234 UpdateMessage();
336 235
337 // Wait for the placeholder to finish loading to hide the premade plugin. 236 // Wait for the placeholder to finish loading to hide the premade plugin.
338 // This is necessary to prevent a flicker. 237 // This is necessary to prevent a flicker.
339 if (premade_throttler_ && power_saver_enabled_) 238 if (premade_throttler_ && power_saver_enabled_)
340 premade_throttler_->SetHiddenForPlaceholder(true /* hidden */); 239 premade_throttler_->SetHiddenForPlaceholder(true /* hidden */);
341 240
342 // Set an attribute and post an event, so browser tests can wait for the 241 // Set an attribute and post an event, so browser tests can wait for the
343 // placeholder to be ready to receive simulated user input. 242 // placeholder to be ready to receive simulated user input.
344 if (base::CommandLine::ForCurrentProcess()->HasSwitch( 243 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
345 switches::kEnablePluginPlaceholderTesting)) { 244 switches::kEnablePluginPlaceholderTesting)) {
346 WebElement element = plugin()->container()->element(); 245 blink::WebElement element = plugin()->container()->element();
347 element.setAttribute("placeholderLoaded", "true"); 246 element.setAttribute("placeholderLoaded", "true");
348 247
349 scoped_ptr<content::V8ValueConverter> converter( 248 scoped_ptr<content::V8ValueConverter> converter(
350 content::V8ValueConverter::create()); 249 content::V8ValueConverter::create());
351 base::StringValue value("placeholderLoaded"); 250 base::StringValue value("placeholderLoaded");
352 blink::WebSerializedScriptValue message_data = 251 blink::WebSerializedScriptValue message_data =
353 blink::WebSerializedScriptValue::serialize(converter->ToV8Value( 252 blink::WebSerializedScriptValue::serialize(converter->ToV8Value(
354 &value, element.document().frame()->mainWorldScriptContext())); 253 &value, element.document().frame()->mainWorldScriptContext()));
355 254
356 blink::WebDOMEvent event = element.document().createEvent("MessageEvent"); 255 blink::WebDOMEvent event = element.document().createEvent("MessageEvent");
(...skipping 26 matching lines...) Expand all
383 return identifier_; 282 return identifier_;
384 } 283 }
385 284
386 bool LoadablePluginPlaceholder::LoadingBlocked() const { 285 bool LoadablePluginPlaceholder::LoadingBlocked() const {
387 DCHECK(allow_loading_); 286 DCHECK(allow_loading_);
388 return is_blocked_for_background_tab_ || is_blocked_for_power_saver_poster_ || 287 return is_blocked_for_background_tab_ || is_blocked_for_power_saver_poster_ ||
389 is_blocked_for_prerendering_; 288 is_blocked_for_prerendering_;
390 } 289 }
391 290
392 } // namespace plugins 291 } // namespace plugins
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698