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

Side by Side Diff: Source/core/html/HTMLPlugInElement.cpp

Issue 23618022: BrowserPlugin/WebView - Move plugin lifetime to DOM (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Address comments. Created 6 years, 12 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 | Annotate | Revision Log
OLDNEW
1 /** 1 /**
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2000 Stefan Schimanski (1Stein@gmx.de) 4 * (C) 2000 Stefan Schimanski (1Stein@gmx.de)
5 * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. 5 * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
6 * 6 *
7 * This library is free software; you can redistribute it and/or 7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public 8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either 9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version. 10 * version 2 of the License, or (at your option) any later version.
(...skipping 15 matching lines...) Expand all
26 #include "CSSPropertyNames.h" 26 #include "CSSPropertyNames.h"
27 #include "HTMLNames.h" 27 #include "HTMLNames.h"
28 #include "bindings/v8/ScriptController.h" 28 #include "bindings/v8/ScriptController.h"
29 #include "bindings/v8/npruntime_impl.h" 29 #include "bindings/v8/npruntime_impl.h"
30 #include "core/dom/Document.h" 30 #include "core/dom/Document.h"
31 #include "core/dom/PostAttachCallbacks.h" 31 #include "core/dom/PostAttachCallbacks.h"
32 #include "core/dom/shadow/ShadowRoot.h" 32 #include "core/dom/shadow/ShadowRoot.h"
33 #include "core/events/Event.h" 33 #include "core/events/Event.h"
34 #include "core/frame/ContentSecurityPolicy.h" 34 #include "core/frame/ContentSecurityPolicy.h"
35 #include "core/frame/Frame.h" 35 #include "core/frame/Frame.h"
36 #include "core/frame/FrameView.h"
36 #include "core/html/HTMLImageLoader.h" 37 #include "core/html/HTMLImageLoader.h"
37 #include "core/html/PluginDocument.h" 38 #include "core/html/PluginDocument.h"
38 #include "core/html/shadow/HTMLContentElement.h" 39 #include "core/html/shadow/HTMLContentElement.h"
39 #include "core/loader/FrameLoaderClient.h" 40 #include "core/loader/FrameLoaderClient.h"
40 #include "core/page/EventHandler.h" 41 #include "core/page/EventHandler.h"
41 #include "core/page/Page.h" 42 #include "core/page/Page.h"
42 #include "core/frame/Settings.h" 43 #include "core/frame/Settings.h"
43 #include "core/plugins/PluginView.h" 44 #include "core/plugins/PluginView.h"
44 #include "core/rendering/RenderEmbeddedObject.h" 45 #include "core/rendering/RenderEmbeddedObject.h"
45 #include "core/rendering/RenderImage.h" 46 #include "core/rendering/RenderImage.h"
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 ASSERT(!m_isDelayingLoadEvent); 78 ASSERT(!m_isDelayingLoadEvent);
78 79
79 if (m_NPObject) { 80 if (m_NPObject) {
80 _NPN_ReleaseObject(m_NPObject); 81 _NPN_ReleaseObject(m_NPObject);
81 m_NPObject = 0; 82 m_NPObject = 0;
82 } 83 }
83 } 84 }
84 85
85 bool HTMLPlugInElement::canProcessDrag() const 86 bool HTMLPlugInElement::canProcessDrag() const
86 { 87 {
87 return pluginWidget() && pluginWidget()->isPluginView() && toPluginView(plug inWidget())->canProcessDrag(); 88 return widget() && widget()->isPluginView() && toPluginView(widget())->canPr ocessDrag();
88 } 89 }
89 90
90 bool HTMLPlugInElement::willRespondToMouseClickEvents() 91 bool HTMLPlugInElement::willRespondToMouseClickEvents()
91 { 92 {
92 if (isDisabledFormControl()) 93 if (isDisabledFormControl())
93 return false; 94 return false;
94 RenderObject* r = renderer(); 95 RenderObject* r = renderer();
95 return r && (r->isEmbeddedObject() || r->isWidget()); 96 return r && (r->isEmbeddedObject() || r->isWidget());
96 } 97 }
97 98
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 void HTMLPlugInElement::updateWidget() 135 void HTMLPlugInElement::updateWidget()
135 { 136 {
136 RefPtr<HTMLPlugInElement> protector(this); 137 RefPtr<HTMLPlugInElement> protector(this);
137 updateWidgetInternal(); 138 updateWidgetInternal();
138 if (m_isDelayingLoadEvent) { 139 if (m_isDelayingLoadEvent) {
139 m_isDelayingLoadEvent = false; 140 m_isDelayingLoadEvent = false;
140 document().decrementLoadEventDelayCount(); 141 document().decrementLoadEventDelayCount();
141 } 142 }
142 } 143 }
143 144
145 void HTMLPlugInElement::requestPluginCreationWithoutRendererIfPossible()
146 {
147 if (m_serviceType.isEmpty())
148 return;
149
150 if (!document().frame()->loader().client()->canCreatePluginWithoutRenderer(m _serviceType))
151 return;
152
153 if (renderer() && renderer()->isWidget())
154 return;
155
156 createPluginWithoutRenderer();
157 }
158
159 void HTMLPlugInElement::createPluginWithoutRenderer()
160 {
161 ASSERT(document().frame()->loader().client()->canCreatePluginWithoutRenderer (m_serviceType));
162
163 KURL url;
164 Vector<String> paramNames;
165 Vector<String> paramValues;
166
167 paramNames.append("type");
168 paramValues.append(m_serviceType);
169
170 bool useFallback = false;
171 loadPlugin(url, m_serviceType, paramNames, paramValues, useFallback, false);
172 }
173
144 void HTMLPlugInElement::detach(const AttachContext& context) 174 void HTMLPlugInElement::detach(const AttachContext& context)
145 { 175 {
146 // Update the widget the next time we attach (detaching destroys the plugin) . 176 // Update the widget the next time we attach (detaching destroys the plugin) .
147 // FIXME: None of this "needsWidgetUpdate" related code looks right. 177 // FIXME: None of this "needsWidgetUpdate" related code looks right.
148 if (renderer() && !useFallbackContent()) 178 if (renderer() && !useFallbackContent())
149 setNeedsWidgetUpdate(true); 179 setNeedsWidgetUpdate(true);
150 if (m_isDelayingLoadEvent) { 180 if (m_isDelayingLoadEvent) {
151 m_isDelayingLoadEvent = false; 181 m_isDelayingLoadEvent = false;
152 document().decrementLoadEventDelayCount(); 182 document().decrementLoadEventDelayCount();
153 } 183 }
154 184
185 Widget* plugin = widget();
186 if (plugin && plugin->pluginShouldPersist())
187 m_persistedPluginWidget = plugin;
155 resetInstance(); 188 resetInstance();
189 setWidget(0);
190
156 191
157 if (m_isCapturingMouseEvents) { 192 if (m_isCapturingMouseEvents) {
158 if (Frame* frame = document().frame()) 193 if (Frame* frame = document().frame())
159 frame->eventHandler().setCapturingMouseEventsNode(0); 194 frame->eventHandler().setCapturingMouseEventsNode(0);
160 m_isCapturingMouseEvents = false; 195 m_isCapturingMouseEvents = false;
161 } 196 }
162 197
163 if (m_NPObject) { 198 if (m_NPObject) {
164 _NPN_ReleaseObject(m_NPObject); 199 _NPN_ReleaseObject(m_NPObject);
165 m_NPObject = 0; 200 m_NPObject = 0;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 SharedPersistent<v8::Object>* HTMLPlugInElement::pluginWrapper() 246 SharedPersistent<v8::Object>* HTMLPlugInElement::pluginWrapper()
212 { 247 {
213 Frame* frame = document().frame(); 248 Frame* frame = document().frame();
214 if (!frame) 249 if (!frame)
215 return 0; 250 return 0;
216 251
217 // If the host dynamically turns off JavaScript (or Java) we will still 252 // If the host dynamically turns off JavaScript (or Java) we will still
218 // return the cached allocated Bindings::Instance. Not supporting this 253 // return the cached allocated Bindings::Instance. Not supporting this
219 // edge-case is OK. 254 // edge-case is OK.
220 if (!m_pluginWrapper) { 255 if (!m_pluginWrapper) {
221 if (Widget* widget = pluginWidget()) 256 Widget* plugin = widget();
222 m_pluginWrapper = frame->script().createPluginWrapper(widget); 257 if (!plugin && m_persistedPluginWidget)
258 plugin = m_persistedPluginWidget.get();
259 if (!plugin && !m_inBeforeLoadEventHandler) {
260 // If the plugin wasn't created without a renderer, then we can
261 // trigger its creation here. Although widgets are no longer owned
262 // by the renderWidget, the creation of the latter will still lead
263 // to loadPlugin() being called.
264 renderWidgetForJSBindings();
265 plugin = widget();
266 }
267 if (plugin)
268 m_pluginWrapper = frame->script().createPluginWrapper(plugin);
223 } 269 }
224 return m_pluginWrapper.get(); 270 return m_pluginWrapper.get();
225 } 271 }
226 272
227 bool HTMLPlugInElement::dispatchBeforeLoadEvent(const String& sourceURL) 273 bool HTMLPlugInElement::dispatchBeforeLoadEvent(const String& sourceURL)
228 { 274 {
229 // FIXME: Our current plug-in loading design can't guarantee the following 275 // FIXME: Our current plug-in loading design can't guarantee the following
230 // assertion is true, since plug-in loading can be initiated during layout, 276 // assertion is true, since plug-in loading can be initiated during layout,
231 // and synchronous layout can be initiated in a beforeload event handler! 277 // and synchronous layout can be initiated in a beforeload event handler!
232 // See <http://webkit.org/b/71264>. 278 // See <http://webkit.org/b/71264>.
233 // ASSERT(!m_inBeforeLoadEventHandler); 279 // ASSERT(!m_inBeforeLoadEventHandler);
234 m_inBeforeLoadEventHandler = true; 280 m_inBeforeLoadEventHandler = true;
235 bool beforeLoadAllowedLoad = HTMLFrameOwnerElement::dispatchBeforeLoadEvent( sourceURL); 281 bool beforeLoadAllowedLoad = HTMLFrameOwnerElement::dispatchBeforeLoadEvent( sourceURL);
236 m_inBeforeLoadEventHandler = false; 282 m_inBeforeLoadEventHandler = false;
237 return beforeLoadAllowedLoad; 283 return beforeLoadAllowedLoad;
238 } 284 }
239 285
240 Widget* HTMLPlugInElement::pluginWidget() const
241 {
242 if (m_inBeforeLoadEventHandler) {
243 // The plug-in hasn't loaded yet, and it makes no sense to try to load
244 // if beforeload handler happened to touch the plug-in element. That
245 // would recursively call beforeload for the same element.
246 return 0;
247 }
248
249 if (RenderWidget* renderWidget = renderWidgetForJSBindings())
250 return renderWidget->widget();
251 return 0;
252 }
253
254 bool HTMLPlugInElement::isPresentationAttribute(const QualifiedName& name) const 286 bool HTMLPlugInElement::isPresentationAttribute(const QualifiedName& name) const
255 { 287 {
256 if (name == widthAttr || name == heightAttr || name == vspaceAttr || name == hspaceAttr || name == alignAttr) 288 if (name == widthAttr || name == heightAttr || name == vspaceAttr || name == hspaceAttr || name == alignAttr)
257 return true; 289 return true;
258 return HTMLFrameOwnerElement::isPresentationAttribute(name); 290 return HTMLFrameOwnerElement::isPresentationAttribute(name);
259 } 291 }
260 292
261 void HTMLPlugInElement::collectStyleForPresentationAttribute(const QualifiedName & name, const AtomicString& value, MutableStylePropertySet* style) 293 void HTMLPlugInElement::collectStyleForPresentationAttribute(const QualifiedName & name, const AtomicString& value, MutableStylePropertySet* style)
262 { 294 {
263 if (name == widthAttr) { 295 if (name == widthAttr) {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 // when JavaScript code accesses the plugin. 345 // when JavaScript code accesses the plugin.
314 // FIXME: Check if dispatching events here is safe. 346 // FIXME: Check if dispatching events here is safe.
315 document().updateLayoutIgnorePendingStylesheets(Document::RunPostLayoutTasks Synchronously); 347 document().updateLayoutIgnorePendingStylesheets(Document::RunPostLayoutTasks Synchronously);
316 return existingRenderWidget(); 348 return existingRenderWidget();
317 } 349 }
318 350
319 bool HTMLPlugInElement::isKeyboardFocusable() const 351 bool HTMLPlugInElement::isKeyboardFocusable() const
320 { 352 {
321 if (!document().isActive()) 353 if (!document().isActive())
322 return false; 354 return false;
323 return pluginWidget() && pluginWidget()->isPluginView() && toPluginView(plug inWidget())->supportsKeyboardFocus(); 355 return widget() && widget()->isPluginView() && toPluginView(widget())->suppo rtsKeyboardFocus();
324 } 356 }
325 357
326 bool HTMLPlugInElement::isPluginElement() const 358 bool HTMLPlugInElement::isPluginElement() const
327 { 359 {
328 return true; 360 return true;
329 } 361 }
330 362
331 bool HTMLPlugInElement::rendererIsFocusable() const 363 bool HTMLPlugInElement::rendererIsFocusable() const
332 { 364 {
333 if (HTMLFrameOwnerElement::supportsFocus() && HTMLFrameOwnerElement::rendere rIsFocusable()) 365 if (HTMLFrameOwnerElement::supportsFocus() && HTMLFrameOwnerElement::rendere rIsFocusable())
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
405 437
406 // FIXME: None of this code should use renderers! 438 // FIXME: None of this code should use renderers!
407 RenderEmbeddedObject* renderer = renderEmbeddedObject(); 439 RenderEmbeddedObject* renderer = renderEmbeddedObject();
408 ASSERT(renderer); 440 ASSERT(renderer);
409 if (!renderer) 441 if (!renderer)
410 return false; 442 return false;
411 443
412 KURL completedURL = document().completeURL(url); 444 KURL completedURL = document().completeURL(url);
413 445
414 bool useFallback; 446 bool useFallback;
447 bool requireRenderer = true;
415 if (shouldUsePlugin(completedURL, mimeType, renderer->hasFallbackContent(), useFallback)) 448 if (shouldUsePlugin(completedURL, mimeType, renderer->hasFallbackContent(), useFallback))
416 return loadPlugin(completedURL, mimeType, paramNames, paramValues, useFa llback); 449 return loadPlugin(completedURL, mimeType, paramNames, paramValues, useFa llback, requireRenderer);
417 450
418 // If the plug-in element already contains a subframe, 451 // If the plug-in element already contains a subframe,
419 // loadOrRedirectSubframe will re-use it. Otherwise, it will create a new 452 // loadOrRedirectSubframe will re-use it. Otherwise, it will create a new
420 // frame and set it as the RenderPart's widget, causing what was previously 453 // frame and set it as the RenderPart's widget, causing what was previously
421 // in the widget to be torn down. 454 // in the widget to be torn down.
422 return loadOrRedirectSubframe(completedURL, getNameAttribute(), true); 455 return loadOrRedirectSubframe(completedURL, getNameAttribute(), true);
423 } 456 }
424 457
425 bool HTMLPlugInElement::loadPlugin(const KURL& url, const String& mimeType, cons t Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallbac k) 458 bool HTMLPlugInElement::loadPlugin(const KURL& url, const String& mimeType, cons t Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallbac k, bool requireRenderer)
426 { 459 {
427 Frame* frame = document().frame(); 460 Frame* frame = document().frame();
428 461
429 if (!frame->loader().allowPlugins(AboutToInstantiatePlugin)) 462 if (!frame->loader().allowPlugins(AboutToInstantiatePlugin))
430 return false; 463 return false;
431 464
432 if (!pluginIsLoadable(url, mimeType)) 465 if (!pluginIsLoadable(url, mimeType))
433 return false; 466 return false;
434 467
435 RenderEmbeddedObject* renderer = renderEmbeddedObject(); 468 RenderEmbeddedObject* renderer = renderEmbeddedObject();
436 // FIXME: This code should not depend on renderer! 469 // FIXME: This code should not depend on renderer!
437 if (!renderer || useFallback) 470 if ((!renderer && requireRenderer) || useFallback)
438 return false; 471 return false;
439 472
473 FrameLoaderClient::PluginLoadType loadType = renderer ? FrameLoaderClient::P luginLoadRequiresRenderer : FrameLoaderClient::PluginLoadWithoutRenderer;
474
440 WTF_LOG(Plugins, "%p Plug-in URL: %s", this, m_url.utf8().data()); 475 WTF_LOG(Plugins, "%p Plug-in URL: %s", this, m_url.utf8().data());
441 WTF_LOG(Plugins, " Loaded URL: %s", url.string().utf8().data()); 476 WTF_LOG(Plugins, " Loaded URL: %s", url.string().utf8().data());
477
442 m_loadedUrl = url; 478 m_loadedUrl = url;
443 479
444 IntSize contentSize = roundedIntSize(LayoutSize(renderer->contentWidth(), re nderer->contentHeight())); 480 IntSize contentSize;
445 bool loadManually = document().isPluginDocument() && !document().containsPlu gins() && toPluginDocument(document()).shouldLoadPluginManually(); 481 if (renderer)
446 RefPtr<Widget> widget = frame->loader().client()->createPlugin(contentSize, this, url, paramNames, paramValues, mimeType, loadManually); 482 contentSize = roundedIntSize(LayoutSize(renderer->contentWidth(), render er->contentHeight()));
483 RefPtr<Widget> plugin = m_persistedPluginWidget;
447 484
448 if (!widget) { 485 if (!plugin) {
449 if (!renderer->showsUnavailablePluginIndicator()) 486 bool loadManually = document().isPluginDocument() && !document().contain sPlugins() && toPluginDocument(document()).shouldLoadPluginManually();
487 plugin = frame->loader().client()->createPlugin(contentSize, this, url, paramNames, paramValues, mimeType, loadManually, loadType);
488 }
489
490 if (!plugin) {
491 if (renderer && !renderer->showsUnavailablePluginIndicator())
450 renderer->setPluginUnavailabilityReason(RenderEmbeddedObject::Plugin Missing); 492 renderer->setPluginUnavailabilityReason(RenderEmbeddedObject::Plugin Missing);
451 return false; 493 return false;
452 } 494 }
453 495
454 renderer->setWidget(widget); 496 ASSERT(plugin->isPluginContainer());
497
498 if (renderer) {
499 setWidget(plugin);
500 m_persistedPluginWidget = 0;
501 } else {
502 if (plugin != m_persistedPluginWidget)
503 m_persistedPluginWidget = plugin;
504 }
455 document().setContainsPlugins(); 505 document().setContainsPlugins();
456 setNeedsStyleRecalc(LocalStyleChange, StyleChangeFromRenderer);
457 return true; 506 return true;
458 } 507 }
459 508
460 bool HTMLPlugInElement::shouldUsePlugin(const KURL& url, const String& mimeType, bool hasFallback, bool& useFallback) 509 bool HTMLPlugInElement::shouldUsePlugin(const KURL& url, const String& mimeType, bool hasFallback, bool& useFallback)
461 { 510 {
462 // Allow other plug-ins to win over QuickTime because if the user has 511 // Allow other plug-ins to win over QuickTime because if the user has
463 // installed a plug-in that can handle TIFF (which QuickTime can also 512 // installed a plug-in that can handle TIFF (which QuickTime can also
464 // handle) they probably intended to override QT. 513 // handle) they probably intended to override QT.
465 if (document().frame()->page() && (mimeType == "image/tiff" || mimeType == " image/tif" || mimeType == "image/x-tiff")) { 514 if (document().frame()->page() && (mimeType == "image/tiff" || mimeType == " image/tif" || mimeType == "image/x-tiff")) {
466 const PluginData* pluginData = document().frame()->page()->pluginData(); 515 const PluginData* pluginData = document().frame()->page()->pluginData();
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
517 if (root.isOldestAuthorShadowRoot()) 566 if (root.isOldestAuthorShadowRoot())
518 lazyReattachIfAttached(); 567 lazyReattachIfAttached();
519 } 568 }
520 569
521 bool HTMLPlugInElement::useFallbackContent() const 570 bool HTMLPlugInElement::useFallbackContent() const
522 { 571 {
523 return hasAuthorShadowRoot(); 572 return hasAuthorShadowRoot();
524 } 573 }
525 574
526 } 575 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698