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

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: Add tests, make plugin creation synchronous. Created 7 years 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/page/Settings.h" 43 #include "core/page/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 16 matching lines...) Expand all
62 , m_NPObject(0) 63 , m_NPObject(0)
63 , m_isCapturingMouseEvents(false) 64 , m_isCapturingMouseEvents(false)
64 , m_inBeforeLoadEventHandler(false) 65 , m_inBeforeLoadEventHandler(false)
65 // m_needsWidgetUpdate(!createdByParser) allows HTMLObjectElement to delay 66 // m_needsWidgetUpdate(!createdByParser) allows HTMLObjectElement to delay
66 // widget updates until after all children are parsed. For HTMLEmbedElement 67 // widget updates until after all children are parsed. For HTMLEmbedElement
67 // this delay is unnecessary, but it is simpler to make both classes share 68 // this delay is unnecessary, but it is simpler to make both classes share
68 // the same codepath in this class. 69 // the same codepath in this class.
69 , m_needsWidgetUpdate(!createdByParser) 70 , m_needsWidgetUpdate(!createdByParser)
70 , m_shouldPreferPlugInsForImages(preferPlugInsForImagesOption == ShouldPrefe rPlugInsForImages) 71 , m_shouldPreferPlugInsForImages(preferPlugInsForImagesOption == ShouldPrefe rPlugInsForImages)
71 , m_displayState(Playing) 72 , m_displayState(Playing)
73 , m_persistedPluginWidget(0)
72 { 74 {
73 setHasCustomStyleCallbacks(); 75 setHasCustomStyleCallbacks();
74 } 76 }
75 77
76 HTMLPlugInElement::~HTMLPlugInElement() 78 HTMLPlugInElement::~HTMLPlugInElement()
77 { 79 {
78 ASSERT(!m_pluginWrapper); // cleared in detach() 80 ASSERT(!m_pluginWrapper); // cleared in detach()
79 ASSERT(!m_isDelayingLoadEvent); 81 ASSERT(!m_isDelayingLoadEvent);
80 82
81 if (m_NPObject) { 83 if (m_NPObject) {
82 _NPN_ReleaseObject(m_NPObject); 84 _NPN_ReleaseObject(m_NPObject);
83 m_NPObject = 0; 85 m_NPObject = 0;
84 } 86 }
85 } 87 }
86 88
87 bool HTMLPlugInElement::canProcessDrag() const 89 bool HTMLPlugInElement::canProcessDrag() const
88 { 90 {
89 return pluginWidget() && pluginWidget()->isPluginView() && toPluginView(plug inWidget())->canProcessDrag(); 91 return widget() && widget()->isPluginView() && toPluginView(widget())->canPr ocessDrag();
90 } 92 }
91 93
92 bool HTMLPlugInElement::willRespondToMouseClickEvents() 94 bool HTMLPlugInElement::willRespondToMouseClickEvents()
93 { 95 {
94 if (isDisabledFormControl()) 96 if (isDisabledFormControl())
95 return false; 97 return false;
96 RenderObject* r = renderer(); 98 RenderObject* r = renderer();
97 return r && (r->isEmbeddedObject() || r->isWidget()); 99 return r && (r->isEmbeddedObject() || r->isWidget());
98 } 100 }
99 101
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
136 void HTMLPlugInElement::updateWidget() 138 void HTMLPlugInElement::updateWidget()
137 { 139 {
138 RefPtr<HTMLPlugInElement> protector(this); 140 RefPtr<HTMLPlugInElement> protector(this);
139 updateWidgetInternal(); 141 updateWidgetInternal();
140 if (m_isDelayingLoadEvent) { 142 if (m_isDelayingLoadEvent) {
141 m_isDelayingLoadEvent = false; 143 m_isDelayingLoadEvent = false;
142 document().decrementLoadEventDelayCount(); 144 document().decrementLoadEventDelayCount();
143 } 145 }
144 } 146 }
145 147
148 void HTMLPlugInElement::requestPluginCreationWithoutRendererIfPossible()
149 {
150 if (m_serviceType.isEmpty())
151 return;
152
153 if (!document().frame()->loader().client()->canCreatePluginWithoutRenderer(m _serviceType))
154 return;
155
156 if (renderer() && renderer()->isWidget())
157 return;
158
159 createPluginWithoutRenderer();
160 }
161
162 void HTMLPlugInElement::createPluginWithoutRenderer()
163 {
164 ASSERT(document().frame()->loader().client()->canCreatePluginWithoutRenderer (m_serviceType));
165
166 KURL url;
167 Vector<String> paramNames;
168 Vector<String> paramValues;
169
170 paramNames.append("type");
171 paramValues.append(m_serviceType);
172
173 bool useFallback = false;
174 loadPlugin(url, m_serviceType, paramNames, paramValues, useFallback, false);
175 }
176
146 void HTMLPlugInElement::detach(const AttachContext& context) 177 void HTMLPlugInElement::detach(const AttachContext& context)
147 { 178 {
148 // Update the widget the next time we attach (detaching destroys the plugin) . 179 // Update the widget the next time we attach (detaching destroys the plugin) .
149 // FIXME: None of this "needsWidgetUpdate" related code looks right. 180 // FIXME: None of this "needsWidgetUpdate" related code looks right.
150 if (renderer() && !useFallbackContent()) 181 if (renderer() && !useFallbackContent())
151 setNeedsWidgetUpdate(true); 182 setNeedsWidgetUpdate(true);
152 if (m_isDelayingLoadEvent) { 183 if (m_isDelayingLoadEvent) {
153 m_isDelayingLoadEvent = false; 184 m_isDelayingLoadEvent = false;
154 document().decrementLoadEventDelayCount(); 185 document().decrementLoadEventDelayCount();
155 } 186 }
156 187
188 Widget* plugin = widget();
189 if (plugin && plugin->pluginShouldPersist())
190 m_persistedPluginWidget = plugin;
157 resetInstance(); 191 resetInstance();
192 setWidget(0);
193
158 194
159 if (m_isCapturingMouseEvents) { 195 if (m_isCapturingMouseEvents) {
160 if (Frame* frame = document().frame()) 196 if (Frame* frame = document().frame())
161 frame->eventHandler().setCapturingMouseEventsNode(0); 197 frame->eventHandler().setCapturingMouseEventsNode(0);
162 m_isCapturingMouseEvents = false; 198 m_isCapturingMouseEvents = false;
163 } 199 }
164 200
165 if (m_NPObject) { 201 if (m_NPObject) {
166 _NPN_ReleaseObject(m_NPObject); 202 _NPN_ReleaseObject(m_NPObject);
167 m_NPObject = 0; 203 m_NPObject = 0;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 SharedPersistent<v8::Object>* HTMLPlugInElement::pluginWrapper() 249 SharedPersistent<v8::Object>* HTMLPlugInElement::pluginWrapper()
214 { 250 {
215 Frame* frame = document().frame(); 251 Frame* frame = document().frame();
216 if (!frame) 252 if (!frame)
217 return 0; 253 return 0;
218 254
219 // If the host dynamically turns off JavaScript (or Java) we will still 255 // If the host dynamically turns off JavaScript (or Java) we will still
220 // return the cached allocated Bindings::Instance. Not supporting this 256 // return the cached allocated Bindings::Instance. Not supporting this
221 // edge-case is OK. 257 // edge-case is OK.
222 if (!m_pluginWrapper) { 258 if (!m_pluginWrapper) {
223 if (Widget* widget = pluginWidget()) 259 Widget* plugin = widget();
224 m_pluginWrapper = frame->script().createPluginWrapper(widget); 260 if (!plugin && m_persistedPluginWidget)
261 plugin = m_persistedPluginWidget.get();
262 if (!plugin && !m_inBeforeLoadEventHandler) {
263 // If the plugin wasn't created without a renderer, then we can
264 // trigger its creation here. Although widgets are no longer owned
265 // by the renderWidget, the creation of the latter will still lead
266 // to loadPlugin() being called.
267 renderWidgetForJSBindings();
268 plugin = widget();
269 }
270 if (plugin)
271 m_pluginWrapper = frame->script().createPluginWrapper(plugin);
225 } 272 }
226 return m_pluginWrapper.get(); 273 return m_pluginWrapper.get();
227 } 274 }
228 275
229 bool HTMLPlugInElement::dispatchBeforeLoadEvent(const String& sourceURL) 276 bool HTMLPlugInElement::dispatchBeforeLoadEvent(const String& sourceURL)
230 { 277 {
231 // FIXME: Our current plug-in loading design can't guarantee the following 278 // FIXME: Our current plug-in loading design can't guarantee the following
232 // assertion is true, since plug-in loading can be initiated during layout, 279 // assertion is true, since plug-in loading can be initiated during layout,
233 // and synchronous layout can be initiated in a beforeload event handler! 280 // and synchronous layout can be initiated in a beforeload event handler!
234 // See <http://webkit.org/b/71264>. 281 // See <http://webkit.org/b/71264>.
235 // ASSERT(!m_inBeforeLoadEventHandler); 282 // ASSERT(!m_inBeforeLoadEventHandler);
236 m_inBeforeLoadEventHandler = true; 283 m_inBeforeLoadEventHandler = true;
237 bool beforeLoadAllowedLoad = HTMLFrameOwnerElement::dispatchBeforeLoadEvent( sourceURL); 284 bool beforeLoadAllowedLoad = HTMLFrameOwnerElement::dispatchBeforeLoadEvent( sourceURL);
238 m_inBeforeLoadEventHandler = false; 285 m_inBeforeLoadEventHandler = false;
239 return beforeLoadAllowedLoad; 286 return beforeLoadAllowedLoad;
240 } 287 }
241 288
242 Widget* HTMLPlugInElement::pluginWidget() const
243 {
244 if (m_inBeforeLoadEventHandler) {
245 // The plug-in hasn't loaded yet, and it makes no sense to try to load
246 // if beforeload handler happened to touch the plug-in element. That
247 // would recursively call beforeload for the same element.
248 return 0;
249 }
250
251 if (RenderWidget* renderWidget = renderWidgetForJSBindings())
252 return renderWidget->widget();
253 return 0;
254 }
255
256 bool HTMLPlugInElement::isPresentationAttribute(const QualifiedName& name) const 289 bool HTMLPlugInElement::isPresentationAttribute(const QualifiedName& name) const
257 { 290 {
258 if (name == widthAttr || name == heightAttr || name == vspaceAttr || name == hspaceAttr || name == alignAttr) 291 if (name == widthAttr || name == heightAttr || name == vspaceAttr || name == hspaceAttr || name == alignAttr)
259 return true; 292 return true;
260 return HTMLFrameOwnerElement::isPresentationAttribute(name); 293 return HTMLFrameOwnerElement::isPresentationAttribute(name);
261 } 294 }
262 295
263 void HTMLPlugInElement::collectStyleForPresentationAttribute(const QualifiedName & name, const AtomicString& value, MutableStylePropertySet* style) 296 void HTMLPlugInElement::collectStyleForPresentationAttribute(const QualifiedName & name, const AtomicString& value, MutableStylePropertySet* style)
264 { 297 {
265 if (name == widthAttr) { 298 if (name == widthAttr) {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
315 // when JavaScript code accesses the plugin. 348 // when JavaScript code accesses the plugin.
316 // FIXME: Check if dispatching events here is safe. 349 // FIXME: Check if dispatching events here is safe.
317 document().updateLayoutIgnorePendingStylesheets(Document::RunPostLayoutTasks Synchronously); 350 document().updateLayoutIgnorePendingStylesheets(Document::RunPostLayoutTasks Synchronously);
318 return existingRenderWidget(); 351 return existingRenderWidget();
319 } 352 }
320 353
321 bool HTMLPlugInElement::isKeyboardFocusable() const 354 bool HTMLPlugInElement::isKeyboardFocusable() const
322 { 355 {
323 if (!document().page()) 356 if (!document().page())
324 return false; 357 return false;
325 return pluginWidget() && pluginWidget()->isPluginView() && toPluginView(plug inWidget())->supportsKeyboardFocus(); 358 return widget() && widget()->isPluginView() && toPluginView(widget())->suppo rtsKeyboardFocus();
326 } 359 }
327 360
328 bool HTMLPlugInElement::isPluginElement() const 361 bool HTMLPlugInElement::isPluginElement() const
329 { 362 {
330 return true; 363 return true;
331 } 364 }
332 365
333 bool HTMLPlugInElement::rendererIsFocusable() const 366 bool HTMLPlugInElement::rendererIsFocusable() const
334 { 367 {
335 if (HTMLFrameOwnerElement::supportsFocus() && HTMLFrameOwnerElement::rendere rIsFocusable()) 368 if (HTMLFrameOwnerElement::supportsFocus() && HTMLFrameOwnerElement::rendere rIsFocusable())
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
407 440
408 // FIXME: None of this code should use renderers! 441 // FIXME: None of this code should use renderers!
409 RenderEmbeddedObject* renderer = renderEmbeddedObject(); 442 RenderEmbeddedObject* renderer = renderEmbeddedObject();
410 ASSERT(renderer); 443 ASSERT(renderer);
411 if (!renderer) 444 if (!renderer)
412 return false; 445 return false;
413 446
414 KURL completedURL = document().completeURL(url); 447 KURL completedURL = document().completeURL(url);
415 448
416 bool useFallback; 449 bool useFallback;
450 bool requireRenderer = true;
417 if (shouldUsePlugin(completedURL, mimeType, renderer->hasFallbackContent(), useFallback)) 451 if (shouldUsePlugin(completedURL, mimeType, renderer->hasFallbackContent(), useFallback))
418 return loadPlugin(completedURL, mimeType, paramNames, paramValues, useFa llback); 452 return loadPlugin(completedURL, mimeType, paramNames, paramValues, useFa llback, requireRenderer);
419 453
420 // If the plug-in element already contains a subframe, 454 // If the plug-in element already contains a subframe,
421 // loadOrRedirectSubframe will re-use it. Otherwise, it will create a new 455 // loadOrRedirectSubframe will re-use it. Otherwise, it will create a new
422 // frame and set it as the RenderPart's widget, causing what was previously 456 // frame and set it as the RenderPart's widget, causing what was previously
423 // in the widget to be torn down. 457 // in the widget to be torn down.
424 return loadOrRedirectSubframe(completedURL, getNameAttribute(), true); 458 return loadOrRedirectSubframe(completedURL, getNameAttribute(), true);
425 } 459 }
426 460
427 bool HTMLPlugInElement::loadPlugin(const KURL& url, const String& mimeType, cons t Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallbac k) 461 bool HTMLPlugInElement::loadPlugin(const KURL& url, const String& mimeType, cons t Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallbac k, bool requireRenderer)
428 { 462 {
429 Frame* frame = document().frame(); 463 Frame* frame = document().frame();
430 464
431 if (!frame->loader().allowPlugins(AboutToInstantiatePlugin)) 465 if (!frame->loader().allowPlugins(AboutToInstantiatePlugin))
432 return false; 466 return false;
433 467
434 if (!pluginIsLoadable(url, mimeType)) 468 if (!pluginIsLoadable(url, mimeType))
435 return false; 469 return false;
436 470
437 RenderEmbeddedObject* renderer = renderEmbeddedObject(); 471 RenderEmbeddedObject* renderer = renderEmbeddedObject();
438 // FIXME: This code should not depend on renderer! 472 // FIXME: This code should not depend on renderer!
439 if (!renderer || useFallback) 473 if ((!renderer && requireRenderer) || useFallback)
440 return false; 474 return false;
441 475
476 FrameLoaderClient::PluginLoadType loadType = renderer ? FrameLoaderClient::P luginLoadRequiresRenderer : FrameLoaderClient::PluginLoadWithoutRenderer;
477
442 WTF_LOG(Plugins, "%p Plug-in URL: %s", this, m_url.utf8().data()); 478 WTF_LOG(Plugins, "%p Plug-in URL: %s", this, m_url.utf8().data());
443 WTF_LOG(Plugins, " Loaded URL: %s", url.string().utf8().data()); 479 WTF_LOG(Plugins, " Loaded URL: %s", url.string().utf8().data());
480
444 m_loadedUrl = url; 481 m_loadedUrl = url;
445 482
446 IntSize contentSize = roundedIntSize(LayoutSize(renderer->contentWidth(), re nderer->contentHeight())); 483 IntSize contentSize;
447 bool loadManually = document().isPluginDocument() && !document().containsPlu gins() && toPluginDocument(document()).shouldLoadPluginManually(); 484 if (renderer)
448 RefPtr<Widget> widget = frame->loader().client()->createPlugin(contentSize, this, url, paramNames, paramValues, mimeType, loadManually); 485 contentSize = roundedIntSize(LayoutSize(renderer->contentWidth(), render er->contentHeight()));
486 RefPtr<Widget> plugin = m_persistedPluginWidget;
449 487
450 if (!widget) { 488 if (!plugin) {
451 if (!renderer->showsUnavailablePluginIndicator()) 489 bool loadManually = document().isPluginDocument() && !document().contain sPlugins() && toPluginDocument(document()).shouldLoadPluginManually();
490 plugin = frame->loader().client()->createPlugin(contentSize, this, url, paramNames, paramValues, mimeType, loadManually, loadType);
491 }
492
493 if (!plugin) {
494 if (renderer && !renderer->showsUnavailablePluginIndicator())
452 renderer->setPluginUnavailabilityReason(RenderEmbeddedObject::Plugin Missing); 495 renderer->setPluginUnavailabilityReason(RenderEmbeddedObject::Plugin Missing);
453 return false; 496 return false;
454 } 497 }
455 498
456 renderer->setWidget(widget); 499 ASSERT(plugin->isPluginContainer());
500
501 if (renderer) {
502 // FIXME: We assume we don't layout without a renderer, but check this a ssumption.
503 setWidget(plugin);
504 m_persistedPluginWidget = 0;
505 } else {
506 if (plugin != m_persistedPluginWidget)
507 m_persistedPluginWidget = plugin;
508 }
509 // FIXME: it may be that nothing has change (we might be continuing to
510 // persist the same plugin? In that case, would we need to recalc style?
511 setNeedsStyleRecalc(LocalStyleChange, StyleChangeFromRenderer);
457 document().setContainsPlugins(); 512 document().setContainsPlugins();
458 setNeedsStyleRecalc(LocalStyleChange, StyleChangeFromRenderer);
459 return true; 513 return true;
460 } 514 }
461 515
462 bool HTMLPlugInElement::shouldUsePlugin(const KURL& url, const String& mimeType, bool hasFallback, bool& useFallback) 516 bool HTMLPlugInElement::shouldUsePlugin(const KURL& url, const String& mimeType, bool hasFallback, bool& useFallback)
463 { 517 {
464 // Allow other plug-ins to win over QuickTime because if the user has 518 // Allow other plug-ins to win over QuickTime because if the user has
465 // installed a plug-in that can handle TIFF (which QuickTime can also 519 // installed a plug-in that can handle TIFF (which QuickTime can also
466 // handle) they probably intended to override QT. 520 // handle) they probably intended to override QT.
467 if (document().frame()->page() && (mimeType == "image/tiff" || mimeType == " image/tif" || mimeType == "image/x-tiff")) { 521 if (document().frame()->page() && (mimeType == "image/tiff" || mimeType == " image/tif" || mimeType == "image/x-tiff")) {
468 const PluginData* pluginData = document().frame()->page()->pluginData(); 522 const PluginData* pluginData = document().frame()->page()->pluginData();
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
519 if (root.isOldestAuthorShadowRoot()) 573 if (root.isOldestAuthorShadowRoot())
520 lazyReattachIfAttached(); 574 lazyReattachIfAttached();
521 } 575 }
522 576
523 bool HTMLPlugInElement::useFallbackContent() const 577 bool HTMLPlugInElement::useFallbackContent() const
524 { 578 {
525 return hasAuthorShadowRoot(); 579 return hasAuthorShadowRoot();
526 } 580 }
527 581
528 } 582 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698