OLD | NEW |
---|---|
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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
75 ASSERT(!m_pluginWrapper); // cleared in detach() | 75 ASSERT(!m_pluginWrapper); // cleared in detach() |
76 | 76 |
77 if (m_NPObject) { | 77 if (m_NPObject) { |
78 _NPN_ReleaseObject(m_NPObject); | 78 _NPN_ReleaseObject(m_NPObject); |
79 m_NPObject = 0; | 79 m_NPObject = 0; |
80 } | 80 } |
81 } | 81 } |
82 | 82 |
83 bool HTMLPlugInElement::canProcessDrag() const | 83 bool HTMLPlugInElement::canProcessDrag() const |
84 { | 84 { |
85 return pluginWidget() && pluginWidget()->isPluginView() && toPluginView(plug inWidget())->canProcessDrag(); | 85 return widget() && widget()->isPluginView() && toPluginView(widget())->canPr ocessDrag(); |
86 } | 86 } |
87 | 87 |
88 bool HTMLPlugInElement::willRespondToMouseClickEvents() | 88 bool HTMLPlugInElement::willRespondToMouseClickEvents() |
89 { | 89 { |
90 if (isDisabledFormControl()) | 90 if (isDisabledFormControl()) |
91 return false; | 91 return false; |
92 RenderObject* r = renderer(); | 92 RenderObject* r = renderer(); |
93 return r && (r->isEmbeddedObject() || r->isWidget()); | 93 return r && (r->isEmbeddedObject() || r->isWidget()); |
94 } | 94 } |
95 | 95 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
129 { | 129 { |
130 toHTMLPlugInElement(n)->updateWidgetIfNecessary(); | 130 toHTMLPlugInElement(n)->updateWidgetIfNecessary(); |
131 } | 131 } |
132 | 132 |
133 void HTMLPlugInElement::updateWidgetIfNecessary() | 133 void HTMLPlugInElement::updateWidgetIfNecessary() |
134 { | 134 { |
135 document().updateStyleIfNeeded(); | 135 document().updateStyleIfNeeded(); |
136 | 136 |
137 if (!needsWidgetUpdate() || useFallbackContent() || isImageType()) | 137 if (!needsWidgetUpdate() || useFallbackContent() || isImageType()) |
138 return; | 138 return; |
139 | |
140 if (!renderEmbeddedObject() && !m_serviceType.isEmpty()) { | |
141 createPluginWithoutRenderer(m_serviceType); | |
142 return; | |
143 } | |
144 | |
139 if (!renderEmbeddedObject() || renderEmbeddedObject()->showsUnavailablePlugi nIndicator()) | 145 if (!renderEmbeddedObject() || renderEmbeddedObject()->showsUnavailablePlugi nIndicator()) |
140 return; | 146 return; |
141 | 147 |
142 updateWidget(CreateOnlyNonNetscapePlugins); | 148 updateWidget(CreateOnlyNonNetscapePlugins); |
143 } | 149 } |
144 | 150 |
151 void HTMLPlugInElement::createPluginWithoutRenderer(const String& mimeType) | |
152 { | |
153 KURL url; | |
154 Vector<String> paramNames; | |
155 Vector<String> paramValues; | |
156 | |
157 paramNames.append("type"); | |
158 paramValues.append(mimeType); | |
159 | |
160 bool useFallback = false; | |
161 if (loadPlugin(url, mimeType, paramNames, paramValues, useFallback)) { | |
162 // Register the bindings with V8 as a scriptable object; normally this | |
163 // as done in getInstance(), but that is only called after a renderer | |
164 // has been assigned. | |
165 // If we've created a plugin without a renderer, it may want to be able | |
166 // to configure itself before attach, so make sure it has a script | |
167 // object. | |
168 // FIXME: Do we need a new script object and plugin wrapper when we | |
169 // create a plugin? Or can we re-use any existing ones? | |
170 Widget* plugin = widget(); | |
171 ASSERT(plugin); | |
172 Frame* frame = document().frame(); | |
173 if (!m_NPObject) | |
174 m_NPObject = frame->script().createScriptObjectForPluginElement(this ); | |
175 m_pluginWrapper = frame->script().createPluginWrapper(plugin); | |
176 } | |
177 } | |
178 | |
145 void HTMLPlugInElement::detach(const AttachContext& context) | 179 void HTMLPlugInElement::detach(const AttachContext& context) |
146 { | 180 { |
147 // Update the widget the next time we attach (detaching destroys the plugin) . | 181 // Update the widget the next time we attach (detaching destroys the plugin) . |
148 // FIXME: None of this "needsWidgetUpdate" related code looks right. | 182 // FIXME: None of this "needsWidgetUpdate" related code looks right. |
149 if (renderer() && !useFallbackContent()) | 183 if (renderer() && !useFallbackContent()) |
150 setNeedsWidgetUpdate(true); | 184 setNeedsWidgetUpdate(true); |
151 | 185 |
152 resetInstance(); | 186 Widget* plugin = widget(); |
187 if (plugin) { | |
eseidel
2013/12/02 16:28:34
Just combine these two ifs into one line?
wjmaclean
2013/12/02 21:51:55
This disappears in the new patch :-)
| |
188 if (!plugin->pluginShouldPersist()) { | |
189 setWidget(0); | |
190 resetInstance(); | |
191 } | |
192 } | |
153 | 193 |
154 if (m_isCapturingMouseEvents) { | 194 if (m_isCapturingMouseEvents) { |
155 if (Frame* frame = document().frame()) | 195 if (Frame* frame = document().frame()) |
156 frame->eventHandler().setCapturingMouseEventsNode(0); | 196 frame->eventHandler().setCapturingMouseEventsNode(0); |
157 m_isCapturingMouseEvents = false; | 197 m_isCapturingMouseEvents = false; |
158 } | 198 } |
159 | 199 |
160 if (m_NPObject) { | 200 if (m_NPObject) { |
161 _NPN_ReleaseObject(m_NPObject); | 201 _NPN_ReleaseObject(m_NPObject); |
162 m_NPObject = 0; | 202 m_NPObject = 0; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
208 SharedPersistent<v8::Object>* HTMLPlugInElement::pluginWrapper() | 248 SharedPersistent<v8::Object>* HTMLPlugInElement::pluginWrapper() |
209 { | 249 { |
210 Frame* frame = document().frame(); | 250 Frame* frame = document().frame(); |
211 if (!frame) | 251 if (!frame) |
212 return 0; | 252 return 0; |
213 | 253 |
214 // If the host dynamically turns off JavaScript (or Java) we will still | 254 // If the host dynamically turns off JavaScript (or Java) we will still |
215 // return the cached allocated Bindings::Instance. Not supporting this | 255 // return the cached allocated Bindings::Instance. Not supporting this |
216 // edge-case is OK. | 256 // edge-case is OK. |
217 if (!m_pluginWrapper) { | 257 if (!m_pluginWrapper) { |
218 if (Widget* widget = pluginWidget()) | 258 if (Widget* plugin = widget()) |
219 m_pluginWrapper = frame->script().createPluginWrapper(widget); | 259 m_pluginWrapper = frame->script().createPluginWrapper(plugin); |
220 } | 260 } |
221 return m_pluginWrapper.get(); | 261 return m_pluginWrapper.get(); |
222 } | 262 } |
223 | 263 |
224 bool HTMLPlugInElement::dispatchBeforeLoadEvent(const String& sourceURL) | 264 bool HTMLPlugInElement::dispatchBeforeLoadEvent(const String& sourceURL) |
225 { | 265 { |
226 // FIXME: Our current plug-in loading design can't guarantee the following | 266 // FIXME: Our current plug-in loading design can't guarantee the following |
227 // assertion is true, since plug-in loading can be initiated during layout, | 267 // assertion is true, since plug-in loading can be initiated during layout, |
228 // and synchronous layout can be initiated in a beforeload event handler! | 268 // and synchronous layout can be initiated in a beforeload event handler! |
229 // See <http://webkit.org/b/71264>. | 269 // See <http://webkit.org/b/71264>. |
230 // ASSERT(!m_inBeforeLoadEventHandler); | 270 // ASSERT(!m_inBeforeLoadEventHandler); |
231 m_inBeforeLoadEventHandler = true; | 271 m_inBeforeLoadEventHandler = true; |
232 bool beforeLoadAllowedLoad = HTMLFrameOwnerElement::dispatchBeforeLoadEvent( sourceURL); | 272 bool beforeLoadAllowedLoad = HTMLFrameOwnerElement::dispatchBeforeLoadEvent( sourceURL); |
233 m_inBeforeLoadEventHandler = false; | 273 m_inBeforeLoadEventHandler = false; |
234 return beforeLoadAllowedLoad; | 274 return beforeLoadAllowedLoad; |
235 } | 275 } |
236 | 276 |
237 Widget* HTMLPlugInElement::pluginWidget() const | |
238 { | |
239 if (m_inBeforeLoadEventHandler) { | |
240 // The plug-in hasn't loaded yet, and it makes no sense to try to load | |
241 // if beforeload handler happened to touch the plug-in element. That | |
242 // would recursively call beforeload for the same element. | |
243 return 0; | |
244 } | |
245 | |
246 if (RenderWidget* renderWidget = renderWidgetForJSBindings()) | |
247 return renderWidget->widget(); | |
248 return 0; | |
249 } | |
250 | |
251 bool HTMLPlugInElement::isPresentationAttribute(const QualifiedName& name) const | 277 bool HTMLPlugInElement::isPresentationAttribute(const QualifiedName& name) const |
252 { | 278 { |
253 if (name == widthAttr || name == heightAttr || name == vspaceAttr || name == hspaceAttr || name == alignAttr) | 279 if (name == widthAttr || name == heightAttr || name == vspaceAttr || name == hspaceAttr || name == alignAttr) |
254 return true; | 280 return true; |
255 return HTMLFrameOwnerElement::isPresentationAttribute(name); | 281 return HTMLFrameOwnerElement::isPresentationAttribute(name); |
256 } | 282 } |
257 | 283 |
258 void HTMLPlugInElement::collectStyleForPresentationAttribute(const QualifiedName & name, const AtomicString& value, MutableStylePropertySet* style) | 284 void HTMLPlugInElement::collectStyleForPresentationAttribute(const QualifiedName & name, const AtomicString& value, MutableStylePropertySet* style) |
259 { | 285 { |
260 if (name == widthAttr) { | 286 if (name == widthAttr) { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
310 // when JavaScript code accesses the plugin. | 336 // when JavaScript code accesses the plugin. |
311 // FIXME: Check if dispatching events here is safe. | 337 // FIXME: Check if dispatching events here is safe. |
312 document().updateLayoutIgnorePendingStylesheets(Document::RunPostLayoutTasks Synchronously); | 338 document().updateLayoutIgnorePendingStylesheets(Document::RunPostLayoutTasks Synchronously); |
313 return existingRenderWidget(); | 339 return existingRenderWidget(); |
314 } | 340 } |
315 | 341 |
316 bool HTMLPlugInElement::isKeyboardFocusable() const | 342 bool HTMLPlugInElement::isKeyboardFocusable() const |
317 { | 343 { |
318 if (!document().page()) | 344 if (!document().page()) |
319 return false; | 345 return false; |
320 return pluginWidget() && pluginWidget()->isPluginView() && toPluginView(plug inWidget())->supportsKeyboardFocus(); | 346 return widget() && widget()->isPluginView() && toPluginView(widget())->suppo rtsKeyboardFocus(); |
321 } | 347 } |
322 | 348 |
323 bool HTMLPlugInElement::isPluginElement() const | 349 bool HTMLPlugInElement::isPluginElement() const |
324 { | 350 { |
325 return true; | 351 return true; |
326 } | 352 } |
327 | 353 |
328 bool HTMLPlugInElement::rendererIsFocusable() const | 354 bool HTMLPlugInElement::rendererIsFocusable() const |
329 { | 355 { |
330 if (HTMLFrameOwnerElement::supportsFocus() && HTMLFrameOwnerElement::rendere rIsFocusable()) | 356 if (HTMLFrameOwnerElement::supportsFocus() && HTMLFrameOwnerElement::rendere rIsFocusable()) |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
422 bool HTMLPlugInElement::loadPlugin(const KURL& url, const String& mimeType, cons t Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallbac k) | 448 bool HTMLPlugInElement::loadPlugin(const KURL& url, const String& mimeType, cons t Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallbac k) |
423 { | 449 { |
424 Frame* frame = document().frame(); | 450 Frame* frame = document().frame(); |
425 | 451 |
426 if (!frame->loader().allowPlugins(AboutToInstantiatePlugin)) | 452 if (!frame->loader().allowPlugins(AboutToInstantiatePlugin)) |
427 return false; | 453 return false; |
428 | 454 |
429 if (!pluginIsLoadable(url, mimeType)) | 455 if (!pluginIsLoadable(url, mimeType)) |
430 return false; | 456 return false; |
431 | 457 |
458 bool canCreateWithoutRenderer = frame->loader().client()->canCreatePluginWit houtRenderer(mimeType); | |
459 | |
432 RenderEmbeddedObject* renderer = renderEmbeddedObject(); | 460 RenderEmbeddedObject* renderer = renderEmbeddedObject(); |
433 // FIXME: This code should not depend on renderer! | 461 // FIXME: This code should not depend on renderer! |
434 if (!renderer || useFallback) | 462 if ((!renderer && !canCreateWithoutRenderer) || useFallback) |
435 return false; | 463 return false; |
436 | 464 |
465 FrameLoaderClient::PluginLoadType loadType = renderer ? FrameLoaderClient::P luginLoadRequiresRenderer : FrameLoaderClient::PluginLoadWithoutRenderer; | |
466 | |
437 LOG(Plugins, "%p Plug-in URL: %s", this, m_url.utf8().data()); | 467 LOG(Plugins, "%p Plug-in URL: %s", this, m_url.utf8().data()); |
438 LOG(Plugins, " Loaded URL: %s", url.string().utf8().data()); | 468 LOG(Plugins, " Loaded URL: %s", url.string().utf8().data()); |
439 m_loadedUrl = url; | 469 m_loadedUrl = url; |
440 | 470 |
441 IntSize contentSize = roundedIntSize(LayoutSize(renderer->contentWidth(), re nderer->contentHeight())); | 471 IntSize contentSize; |
442 bool loadManually = document().isPluginDocument() && !document().containsPlu gins() && toPluginDocument(document()).shouldLoadPluginManually(); | 472 if (renderer) |
443 RefPtr<Widget> widget = frame->loader().client()->createPlugin(contentSize, this, url, paramNames, paramValues, mimeType, loadManually); | 473 contentSize = roundedIntSize(LayoutSize(renderer->contentWidth(), render er->contentHeight())); |
474 RefPtr<Widget> plugin = widget(); | |
444 | 475 |
445 if (!widget) { | 476 if (!plugin) { |
446 if (!renderer->showsUnavailablePluginIndicator()) | 477 bool loadManually = document().isPluginDocument() && !document().contain sPlugins() && toPluginDocument(document()).shouldLoadPluginManually(); |
478 plugin = frame->loader().client()->createPlugin(contentSize, this, url, paramNames, paramValues, mimeType, loadManually, loadType); | |
479 } | |
480 | |
481 if (!plugin) { | |
482 if (renderer && !renderer->showsUnavailablePluginIndicator()) | |
447 renderer->setPluginUnavailabilityReason(RenderEmbeddedObject::Plugin Missing); | 483 renderer->setPluginUnavailabilityReason(RenderEmbeddedObject::Plugin Missing); |
448 return false; | 484 return false; |
449 } | 485 } |
450 | 486 |
451 renderer->setWidget(widget); | 487 ASSERT(plugin->isPluginContainer()); |
488 setWidget(plugin); | |
489 | |
490 if (renderer) { | |
491 // FIXME: We assume we don't layout without a renderer, but check this a ssumption. | |
eseidel
2013/12/02 16:28:34
style recalc creates/destroys renderers. I doubt
wjmaclean
2013/12/02 21:51:55
Thanks, that's useful to know. I'll remove the if(
| |
492 setNeedsStyleRecalc(LocalStyleChange, StyleChangeFromRenderer); | |
493 } | |
452 document().setContainsPlugins(); | 494 document().setContainsPlugins(); |
453 setNeedsStyleRecalc(LocalStyleChange, StyleChangeFromRenderer); | |
454 return true; | 495 return true; |
455 } | 496 } |
456 | 497 |
457 bool HTMLPlugInElement::shouldUsePlugin(const KURL& url, const String& mimeType, bool hasFallback, bool& useFallback) | 498 bool HTMLPlugInElement::shouldUsePlugin(const KURL& url, const String& mimeType, bool hasFallback, bool& useFallback) |
458 { | 499 { |
459 // Allow other plug-ins to win over QuickTime because if the user has | 500 // Allow other plug-ins to win over QuickTime because if the user has |
460 // installed a plug-in that can handle TIFF (which QuickTime can also | 501 // installed a plug-in that can handle TIFF (which QuickTime can also |
461 // handle) they probably intended to override QT. | 502 // handle) they probably intended to override QT. |
462 if (document().frame()->page() && (mimeType == "image/tiff" || mimeType == " image/tif" || mimeType == "image/x-tiff")) { | 503 if (document().frame()->page() && (mimeType == "image/tiff" || mimeType == " image/tif" || mimeType == "image/x-tiff")) { |
463 const PluginData* pluginData = document().frame()->page()->pluginData(); | 504 const PluginData* pluginData = document().frame()->page()->pluginData(); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
498 if (!document().contentSecurityPolicy()->allowObjectFromSource(url) | 539 if (!document().contentSecurityPolicy()->allowObjectFromSource(url) |
499 || !document().contentSecurityPolicy()->allowPluginType(mimeType, declar edMimeType, url)) { | 540 || !document().contentSecurityPolicy()->allowPluginType(mimeType, declar edMimeType, url)) { |
500 renderEmbeddedObject()->setPluginUnavailabilityReason(RenderEmbeddedObje ct::PluginBlockedByContentSecurityPolicy); | 541 renderEmbeddedObject()->setPluginUnavailabilityReason(RenderEmbeddedObje ct::PluginBlockedByContentSecurityPolicy); |
501 return false; | 542 return false; |
502 } | 543 } |
503 | 544 |
504 return frame->loader().mixedContentChecker()->canRunInsecureContent(document ().securityOrigin(), url); | 545 return frame->loader().mixedContentChecker()->canRunInsecureContent(document ().securityOrigin(), url); |
505 } | 546 } |
506 | 547 |
507 } | 548 } |
OLD | NEW |