Chromium Code Reviews| 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 |