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 15 matching lines...) Expand all Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |