Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / html / HTMLPlugInElement.cpp
1 /**
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  *           (C) 2000 Stefan Schimanski (1Stein@gmx.de)
5  * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public License
18  * along with this library; see the file COPYING.LIB.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 #include "config.h"
24 #include "core/html/HTMLPlugInElement.h"
25
26 #include "bindings/core/v8/ScriptController.h"
27 #include "bindings/core/v8/npruntime_impl.h"
28 #include "core/CSSPropertyNames.h"
29 #include "core/HTMLNames.h"
30 #include "core/dom/Document.h"
31 #include "core/dom/Node.h"
32 #include "core/dom/shadow/ShadowRoot.h"
33 #include "core/events/Event.h"
34 #include "core/frame/FrameView.h"
35 #include "core/frame/LocalFrame.h"
36 #include "core/frame/Settings.h"
37 #include "core/frame/csp/ContentSecurityPolicy.h"
38 #include "core/html/HTMLContentElement.h"
39 #include "core/html/HTMLImageLoader.h"
40 #include "core/html/PluginDocument.h"
41 #include "core/loader/FrameLoaderClient.h"
42 #include "core/page/EventHandler.h"
43 #include "core/page/Page.h"
44 #include "core/page/scrolling/ScrollingCoordinator.h"
45 #include "core/plugins/PluginPlaceholder.h"
46 #include "core/plugins/PluginView.h"
47 #include "core/rendering/RenderBlockFlow.h"
48 #include "core/rendering/RenderEmbeddedObject.h"
49 #include "core/rendering/RenderImage.h"
50 #include "core/rendering/RenderPart.h"
51 #include "platform/Logging.h"
52 #include "platform/MIMETypeFromURL.h"
53 #include "platform/MIMETypeRegistry.h"
54 #include "platform/Widget.h"
55 #include "platform/plugins/PluginData.h"
56
57 namespace blink {
58
59 using namespace HTMLNames;
60
61 HTMLPlugInElement::HTMLPlugInElement(const QualifiedName& tagName, Document& doc, bool createdByParser, PreferPlugInsForImagesOption preferPlugInsForImagesOption)
62     : HTMLFrameOwnerElement(tagName, doc)
63     , m_isDelayingLoadEvent(false)
64     , m_NPObject(0)
65     , m_isCapturingMouseEvents(false)
66     // m_needsWidgetUpdate(!createdByParser) allows HTMLObjectElement to delay
67     // widget updates until after all children are parsed. For HTMLEmbedElement
68     // this delay is unnecessary, but it is simpler to make both classes share
69     // the same codepath in this class.
70     , m_needsWidgetUpdate(!createdByParser)
71     , m_shouldPreferPlugInsForImages(preferPlugInsForImagesOption == ShouldPreferPlugInsForImages)
72 {
73 }
74
75 HTMLPlugInElement::~HTMLPlugInElement()
76 {
77     ASSERT(!m_pluginWrapper); // cleared in detach()
78     ASSERT(!m_isDelayingLoadEvent);
79
80     if (m_NPObject) {
81         _NPN_ReleaseObject(m_NPObject);
82         m_NPObject = 0;
83     }
84 }
85
86 void HTMLPlugInElement::trace(Visitor* visitor)
87 {
88     visitor->trace(m_imageLoader);
89     visitor->trace(m_placeholder);
90     visitor->trace(m_persistedPluginWidget);
91     HTMLFrameOwnerElement::trace(visitor);
92 }
93
94 #if ENABLE(OILPAN)
95 void HTMLPlugInElement::disconnectContentFrame()
96 {
97     if (m_persistedPluginWidget) {
98         m_persistedPluginWidget->dispose();
99         m_persistedPluginWidget = nullptr;
100     }
101     HTMLFrameOwnerElement::disconnectContentFrame();
102 }
103
104 void HTMLPlugInElement::shouldDisposePlugin()
105 {
106     if (m_persistedPluginWidget && m_persistedPluginWidget->isPluginView())
107         toPluginView(m_persistedPluginWidget.get())->shouldDisposePlugin();
108 }
109 #endif
110
111 void HTMLPlugInElement::setPersistedPluginWidget(Widget* widget)
112 {
113     if (m_persistedPluginWidget == widget)
114         return;
115 #if ENABLE(OILPAN)
116     if (m_persistedPluginWidget && m_persistedPluginWidget->isPluginView()) {
117         LocalFrame* frame = toPluginView(m_persistedPluginWidget.get())->pluginFrame();
118         ASSERT(frame);
119         frame->unregisterPluginElement(this);
120     }
121     if (widget && widget->isPluginView()) {
122         LocalFrame* frame = toPluginView(widget)->pluginFrame();
123         ASSERT(frame);
124         frame->registerPluginElement(this);
125     }
126 #endif
127     m_persistedPluginWidget = widget;
128 }
129
130 bool HTMLPlugInElement::canProcessDrag() const
131 {
132     return pluginWidget() && pluginWidget()->isPluginView() && toPluginView(pluginWidget())->canProcessDrag();
133 }
134
135 bool HTMLPlugInElement::willRespondToMouseClickEvents()
136 {
137     if (isDisabledFormControl())
138         return false;
139     RenderObject* r = renderer();
140     return r && (r->isEmbeddedObject() || r->isRenderPart());
141 }
142
143 void HTMLPlugInElement::removeAllEventListeners()
144 {
145     HTMLFrameOwnerElement::removeAllEventListeners();
146     if (RenderPart* renderer = existingRenderPart()) {
147         if (Widget* widget = renderer->widget())
148             widget->eventListenersRemoved();
149     }
150 }
151
152 void HTMLPlugInElement::didMoveToNewDocument(Document& oldDocument)
153 {
154     if (m_imageLoader)
155         m_imageLoader->elementDidMoveToNewDocument();
156     HTMLFrameOwnerElement::didMoveToNewDocument(oldDocument);
157 }
158
159 void HTMLPlugInElement::attach(const AttachContext& context)
160 {
161     HTMLFrameOwnerElement::attach(context);
162
163     if (!renderer() || useFallbackContent())
164         return;
165
166     if (isImageType()) {
167         if (!m_imageLoader)
168             m_imageLoader = HTMLImageLoader::create(this);
169         m_imageLoader->updateFromElement();
170     } else if (needsWidgetUpdate()
171         && renderEmbeddedObject()
172         && !renderEmbeddedObject()->showsUnavailablePluginIndicator()
173         && !wouldLoadAsNetscapePlugin(m_url, m_serviceType)
174         && !m_isDelayingLoadEvent) {
175         m_isDelayingLoadEvent = true;
176         document().incrementLoadEventDelayCount();
177         document().loadPluginsSoon();
178     }
179 }
180
181 void HTMLPlugInElement::updateWidget()
182 {
183     RefPtrWillBeRawPtr<HTMLPlugInElement> protector(this);
184     updateWidgetInternal();
185     if (m_isDelayingLoadEvent) {
186         m_isDelayingLoadEvent = false;
187         document().decrementLoadEventDelayCount();
188     }
189 }
190
191 void HTMLPlugInElement::requestPluginCreationWithoutRendererIfPossible()
192 {
193     if (m_serviceType.isEmpty())
194         return;
195
196     if (!document().frame()
197         || !document().frame()->loader().client()->canCreatePluginWithoutRenderer(m_serviceType))
198         return;
199
200     if (renderer() && renderer()->isRenderPart())
201         return;
202
203     createPluginWithoutRenderer();
204 }
205
206 void HTMLPlugInElement::createPluginWithoutRenderer()
207 {
208     ASSERT(document().frame()->loader().client()->canCreatePluginWithoutRenderer(m_serviceType));
209
210     KURL url;
211     Vector<String> paramNames;
212     Vector<String> paramValues;
213
214     paramNames.append("type");
215     paramValues.append(m_serviceType);
216
217     bool useFallback = false;
218     loadPlugin(url, m_serviceType, paramNames, paramValues, useFallback, false);
219 }
220
221 bool HTMLPlugInElement::shouldAccelerate() const
222 {
223     if (Widget* widget = ownedWidget())
224         return widget->isPluginView() && toPluginView(widget)->platformLayer();
225     return false;
226 }
227
228 void HTMLPlugInElement::detach(const AttachContext& context)
229 {
230     // Update the widget the next time we attach (detaching destroys the plugin).
231     // FIXME: None of this "needsWidgetUpdate" related code looks right.
232     if (renderer() && !useFallbackContent())
233         setNeedsWidgetUpdate(true);
234     if (m_isDelayingLoadEvent) {
235         m_isDelayingLoadEvent = false;
236         document().decrementLoadEventDelayCount();
237     }
238
239     // Only try to persist a plugin widget we actually own.
240     Widget* plugin = ownedWidget();
241     if (plugin && plugin->pluginShouldPersist())
242         setPersistedPluginWidget(plugin);
243
244     resetInstance();
245     // Clear the widget; will trigger disposal of it with Oilpan.
246     setWidget(nullptr);
247
248     if (m_isCapturingMouseEvents) {
249         if (LocalFrame* frame = document().frame())
250             frame->eventHandler().setCapturingMouseEventsNode(nullptr);
251         m_isCapturingMouseEvents = false;
252     }
253
254     if (m_NPObject) {
255         _NPN_ReleaseObject(m_NPObject);
256         m_NPObject = 0;
257     }
258
259     HTMLFrameOwnerElement::detach(context);
260 }
261
262 RenderObject* HTMLPlugInElement::createRenderer(RenderStyle* style)
263 {
264     // Fallback content breaks the DOM->Renderer class relationship of this
265     // class and all superclasses because createObject won't necessarily return
266     // a RenderEmbeddedObject or RenderPart.
267     if (useFallbackContent())
268         return RenderObject::createObject(this, style);
269
270     if (isImageType()) {
271         RenderImage* image = new RenderImage(this);
272         image->setImageResource(RenderImageResource::create());
273         return image;
274     }
275
276     if (usePlaceholderContent())
277         return new RenderBlockFlow(this);
278
279     return new RenderEmbeddedObject(this);
280 }
281
282 void HTMLPlugInElement::finishParsingChildren()
283 {
284     HTMLFrameOwnerElement::finishParsingChildren();
285     if (useFallbackContent())
286         return;
287
288     setNeedsWidgetUpdate(true);
289     if (inDocument())
290         lazyReattachIfNeeded();
291 }
292
293 void HTMLPlugInElement::resetInstance()
294 {
295     m_pluginWrapper.clear();
296 }
297
298 SharedPersistent<v8::Object>* HTMLPlugInElement::pluginWrapper()
299 {
300     LocalFrame* frame = document().frame();
301     if (!frame)
302         return nullptr;
303
304     // If the host dynamically turns off JavaScript (or Java) we will still
305     // return the cached allocated Bindings::Instance. Not supporting this
306     // edge-case is OK.
307     if (!m_pluginWrapper) {
308         Widget* plugin;
309
310         if (m_persistedPluginWidget)
311             plugin = m_persistedPluginWidget.get();
312         else
313             plugin = pluginWidget();
314
315         if (plugin)
316             m_pluginWrapper = frame->script().createPluginWrapper(plugin);
317     }
318     return m_pluginWrapper.get();
319 }
320
321 Widget* HTMLPlugInElement::pluginWidget() const
322 {
323     if (RenderPart* renderPart = renderPartForJSBindings())
324         return renderPart->widget();
325     return nullptr;
326 }
327
328 bool HTMLPlugInElement::isPresentationAttribute(const QualifiedName& name) const
329 {
330     if (name == widthAttr || name == heightAttr || name == vspaceAttr || name == hspaceAttr || name == alignAttr)
331         return true;
332     return HTMLFrameOwnerElement::isPresentationAttribute(name);
333 }
334
335 void HTMLPlugInElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStylePropertySet* style)
336 {
337     if (name == widthAttr) {
338         addHTMLLengthToStyle(style, CSSPropertyWidth, value);
339     } else if (name == heightAttr) {
340         addHTMLLengthToStyle(style, CSSPropertyHeight, value);
341     } else if (name == vspaceAttr) {
342         addHTMLLengthToStyle(style, CSSPropertyMarginTop, value);
343         addHTMLLengthToStyle(style, CSSPropertyMarginBottom, value);
344     } else if (name == hspaceAttr) {
345         addHTMLLengthToStyle(style, CSSPropertyMarginLeft, value);
346         addHTMLLengthToStyle(style, CSSPropertyMarginRight, value);
347     } else if (name == alignAttr) {
348         applyAlignmentAttributeToStyle(value, style);
349     } else {
350         HTMLFrameOwnerElement::collectStyleForPresentationAttribute(name, value, style);
351     }
352 }
353
354 void HTMLPlugInElement::defaultEventHandler(Event* event)
355 {
356     // Firefox seems to use a fake event listener to dispatch events to plug-in
357     // (tested with mouse events only). This is observable via different order
358     // of events - in Firefox, event listeners specified in HTML attributes
359     // fires first, then an event gets dispatched to plug-in, and only then
360     // other event listeners fire. Hopefully, this difference does not matter in
361     // practice.
362
363     // FIXME: Mouse down and scroll events are passed down to plug-in via custom
364     // code in EventHandler; these code paths should be united.
365
366     RenderObject* r = renderer();
367     if (!r || !r->isRenderPart())
368         return;
369     if (r->isEmbeddedObject()) {
370         if (toRenderEmbeddedObject(r)->showsUnavailablePluginIndicator())
371             return;
372     }
373     RefPtrWillBeRawPtr<Widget> widget = toRenderPart(r)->widget();
374     if (!widget)
375         return;
376     widget->handleEvent(event);
377     if (event->defaultHandled())
378         return;
379     HTMLFrameOwnerElement::defaultEventHandler(event);
380 }
381
382 RenderPart* HTMLPlugInElement::renderPartForJSBindings() const
383 {
384     // Needs to load the plugin immediatedly because this function is called
385     // when JavaScript code accesses the plugin.
386     // FIXME: Check if dispatching events here is safe.
387     document().updateLayoutIgnorePendingStylesheets(Document::RunPostLayoutTasksSynchronously);
388     return existingRenderPart();
389 }
390
391 bool HTMLPlugInElement::isKeyboardFocusable() const
392 {
393     if (!document().isActive())
394         return false;
395     return pluginWidget() && pluginWidget()->isPluginView() && toPluginView(pluginWidget())->supportsKeyboardFocus();
396 }
397
398 bool HTMLPlugInElement::hasCustomFocusLogic() const
399 {
400     return !hasAuthorShadowRoot();
401 }
402
403 bool HTMLPlugInElement::isPluginElement() const
404 {
405     return true;
406 }
407
408 bool HTMLPlugInElement::rendererIsFocusable() const
409 {
410     if (HTMLFrameOwnerElement::supportsFocus() && HTMLFrameOwnerElement::rendererIsFocusable())
411         return true;
412
413     if (useFallbackContent() || !renderer() || !renderer()->isEmbeddedObject())
414         return false;
415     return !toRenderEmbeddedObject(renderer())->showsUnavailablePluginIndicator();
416 }
417
418 NPObject* HTMLPlugInElement::getNPObject()
419 {
420     ASSERT(document().frame());
421     if (!m_NPObject)
422         m_NPObject = document().frame()->script().createScriptObjectForPluginElement(this);
423     return m_NPObject;
424 }
425
426 bool HTMLPlugInElement::isImageType()
427 {
428     if (m_serviceType.isEmpty() && protocolIs(m_url, "data"))
429         m_serviceType = mimeTypeFromDataURL(m_url);
430
431     if (LocalFrame* frame = document().frame()) {
432         KURL completedURL = document().completeURL(m_url);
433         return frame->loader().client()->objectContentType(completedURL, m_serviceType, shouldPreferPlugInsForImages()) == ObjectContentImage;
434     }
435
436     return Image::supportsType(m_serviceType);
437 }
438
439 RenderEmbeddedObject* HTMLPlugInElement::renderEmbeddedObject() const
440 {
441     // HTMLObjectElement and HTMLEmbedElement may return arbitrary renderers
442     // when using fallback content.
443     if (!renderer() || !renderer()->isEmbeddedObject())
444         return nullptr;
445     return toRenderEmbeddedObject(renderer());
446 }
447
448 // We don't use m_url, as it may not be the final URL that the object loads,
449 // depending on <param> values.
450 bool HTMLPlugInElement::allowedToLoadFrameURL(const String& url)
451 {
452     KURL completeURL = document().completeURL(url);
453     if (contentFrame() && protocolIsJavaScript(completeURL)
454         && !document().securityOrigin()->canAccess(contentDocument()->securityOrigin()))
455         return false;
456     return document().frame()->isURLAllowed(completeURL);
457 }
458
459 // We don't use m_url, or m_serviceType as they may not be the final values
460 // that <object> uses depending on <param> values.
461 bool HTMLPlugInElement::wouldLoadAsNetscapePlugin(const String& url, const String& serviceType)
462 {
463     ASSERT(document().frame());
464     KURL completedURL;
465     if (!url.isEmpty())
466         completedURL = document().completeURL(url);
467     return document().frame()->loader().client()->objectContentType(completedURL, serviceType, shouldPreferPlugInsForImages()) == ObjectContentNetscapePlugin;
468 }
469
470 bool HTMLPlugInElement::requestObject(const String& url, const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues)
471 {
472     if (url.isEmpty() && mimeType.isEmpty())
473         return false;
474
475     if (protocolIsJavaScript(url))
476         return false;
477
478     // FIXME: None of this code should use renderers!
479     RenderEmbeddedObject* renderer = renderEmbeddedObject();
480     ASSERT(renderer);
481     if (!renderer)
482         return false;
483
484     KURL completedURL = document().completeURL(url);
485     if (!pluginIsLoadable(completedURL, mimeType))
486         return false;
487
488     bool useFallback;
489     bool requireRenderer = true;
490     if (shouldUsePlugin(completedURL, mimeType, hasFallbackContent(), useFallback))
491         return loadPlugin(completedURL, mimeType, paramNames, paramValues, useFallback, requireRenderer);
492
493     // If the plug-in element already contains a subframe,
494     // loadOrRedirectSubframe will re-use it. Otherwise, it will create a new
495     // frame and set it as the RenderPart's widget, causing what was previously
496     // in the widget to be torn down.
497     return loadOrRedirectSubframe(completedURL, getNameAttribute(), true);
498 }
499
500 bool HTMLPlugInElement::loadPlugin(const KURL& url, const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback, bool requireRenderer)
501 {
502     LocalFrame* frame = document().frame();
503
504     if (!frame->loader().allowPlugins(AboutToInstantiatePlugin))
505         return false;
506
507     RenderEmbeddedObject* renderer = renderEmbeddedObject();
508     // FIXME: This code should not depend on renderer!
509     if ((!renderer && requireRenderer) || useFallback)
510         return false;
511
512     WTF_LOG(Plugins, "%p Plug-in URL: %s", this, m_url.utf8().data());
513     WTF_LOG(Plugins, "   Loaded URL: %s", url.string().utf8().data());
514     m_loadedUrl = url;
515
516     OwnPtrWillBeRawPtr<PluginPlaceholder> placeholder = nullptr;
517     RefPtrWillBeRawPtr<Widget> widget = m_persistedPluginWidget;
518     if (!widget) {
519         bool loadManually = document().isPluginDocument() && !document().containsPlugins();
520         placeholder = frame->loader().client()->createPluginPlaceholder(document(), url, paramNames, paramValues, mimeType, loadManually);
521         if (!placeholder) {
522             FrameLoaderClient::DetachedPluginPolicy policy = requireRenderer ? FrameLoaderClient::FailOnDetachedPlugin : FrameLoaderClient::AllowDetachedPlugin;
523             widget = frame->loader().client()->createPlugin(this, url, paramNames, paramValues, mimeType, loadManually, policy);
524         }
525     }
526
527     if (!placeholder && !widget) {
528         if (renderer && !renderer->showsUnavailablePluginIndicator())
529             renderer->setPluginUnavailabilityReason(RenderEmbeddedObject::PluginMissing);
530         setPlaceholder(nullptr);
531         return false;
532     }
533
534     if (placeholder) {
535         setPlaceholder(placeholder.release());
536         return true;
537     }
538
539     if (renderer) {
540         setWidget(widget);
541         setPersistedPluginWidget(nullptr);
542     } else {
543         setPersistedPluginWidget(widget.get());
544     }
545     setPlaceholder(nullptr);
546     document().setContainsPlugins();
547     scheduleSVGFilterLayerUpdateHack();
548     // Make sure any input event handlers introduced by the plugin are taken into account.
549     if (Page* page = document().frame()->page()) {
550         if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
551             scrollingCoordinator->notifyLayoutUpdated();
552     }
553     return true;
554 }
555
556 bool HTMLPlugInElement::shouldUsePlugin(const KURL& url, const String& mimeType, bool hasFallback, bool& useFallback)
557 {
558     // Allow other plug-ins to win over QuickTime because if the user has
559     // installed a plug-in that can handle TIFF (which QuickTime can also
560     // handle) they probably intended to override QT.
561     if (document().frame()->page() && (mimeType == "image/tiff" || mimeType == "image/tif" || mimeType == "image/x-tiff")) {
562         const PluginData* pluginData = document().frame()->page()->pluginData();
563         String pluginName = pluginData ? pluginData->pluginNameForMimeType(mimeType) : String();
564         if (!pluginName.isEmpty() && !pluginName.contains("QuickTime", false))
565             return true;
566     }
567
568     ObjectContentType objectType = document().frame()->loader().client()->objectContentType(url, mimeType, shouldPreferPlugInsForImages());
569     // If an object's content can't be handled and it has no fallback, let
570     // it be handled as a plugin to show the broken plugin icon.
571     useFallback = objectType == ObjectContentNone && hasFallback;
572     return objectType == ObjectContentNone || objectType == ObjectContentNetscapePlugin || objectType == ObjectContentOtherPlugin;
573 }
574
575 void HTMLPlugInElement::setPlaceholder(PassOwnPtrWillBeRawPtr<PluginPlaceholder> placeholder)
576 {
577     bool needsLazyReattach = (!placeholder) != (!m_placeholder);
578     if (placeholder) {
579         placeholder->loadIntoContainer(ensureUserAgentShadowRoot());
580         m_placeholder = placeholder;
581     } else {
582         ShadowRoot& shadowRoot = ensureUserAgentShadowRoot();
583         shadowRoot.removeChildren();
584         shadowRoot.appendChild(HTMLContentElement::create(document()));
585         m_placeholder.clear();
586     }
587     if (needsLazyReattach)
588         lazyReattachIfAttached();
589 }
590
591 void HTMLPlugInElement::dispatchErrorEvent()
592 {
593     if (document().isPluginDocument() && document().ownerElement())
594         document().ownerElement()->dispatchEvent(Event::create(EventTypeNames::error));
595     else
596         dispatchEvent(Event::create(EventTypeNames::error));
597 }
598
599 bool HTMLPlugInElement::pluginIsLoadable(const KURL& url, const String& mimeType)
600 {
601     LocalFrame* frame = document().frame();
602     Settings* settings = frame->settings();
603     if (!settings)
604         return false;
605
606     if (MIMETypeRegistry::isJavaAppletMIMEType(mimeType) && !settings->javaEnabled())
607         return false;
608
609     if (document().isSandboxed(SandboxPlugins))
610         return false;
611
612     if (!document().securityOrigin()->canDisplay(url)) {
613         FrameLoader::reportLocalLoadFailed(frame, url.string());
614         return false;
615     }
616
617     AtomicString declaredMimeType = document().isPluginDocument() && document().ownerElement() ?
618         document().ownerElement()->fastGetAttribute(HTMLNames::typeAttr) :
619         fastGetAttribute(HTMLNames::typeAttr);
620     if (!document().contentSecurityPolicy()->allowObjectFromSource(url)
621         || !document().contentSecurityPolicy()->allowPluginType(mimeType, declaredMimeType, url)) {
622         renderEmbeddedObject()->setPluginUnavailabilityReason(RenderEmbeddedObject::PluginBlockedByContentSecurityPolicy);
623         return false;
624     }
625
626     return frame->loader().mixedContentChecker()->canRunInsecureContent(document().securityOrigin(), url);
627 }
628
629 void HTMLPlugInElement::didAddUserAgentShadowRoot(ShadowRoot&)
630 {
631     userAgentShadowRoot()->appendChild(HTMLContentElement::create(document()));
632 }
633
634 void HTMLPlugInElement::willAddFirstAuthorShadowRoot()
635 {
636     lazyReattachIfAttached();
637 }
638
639 bool HTMLPlugInElement::hasFallbackContent() const
640 {
641     return false;
642 }
643
644 bool HTMLPlugInElement::useFallbackContent() const
645 {
646     return hasAuthorShadowRoot();
647 }
648
649 void HTMLPlugInElement::lazyReattachIfNeeded()
650 {
651     if (!useFallbackContent() && !usePlaceholderContent() && needsWidgetUpdate() && renderer() && !isImageType())
652         lazyReattachIfAttached();
653 }
654
655 }