Fix for object element to support fallback content. WIth this change Safari passes...
authorhyatt <hyatt@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 3 May 2005 20:47:27 +0000 (20:47 +0000)
committerhyatt <hyatt@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 3 May 2005 20:47:27 +0000 (20:47 +0000)
        Reviewed by Maciej

        * khtml/css/html4.css:
        * khtml/html/html_objectimpl.cpp:
        (HTMLObjectElementImpl::HTMLObjectElementImpl):
        (HTMLObjectElementImpl::parseHTMLAttribute):
        (HTMLObjectElementImpl::rendererIsNeeded):
        (HTMLObjectElementImpl::createRenderer):
        (HTMLObjectElementImpl::attach):
        (HTMLObjectElementImpl::detach):
        (HTMLObjectElementImpl::recalcStyle):
        (HTMLObjectElementImpl::childrenChanged):
        (HTMLObjectElementImpl::isURLAttribute):
        (HTMLObjectElementImpl::isImageType):
        (HTMLObjectElementImpl::renderFallbackContent):
        * khtml/html/html_objectimpl.h:
        * khtml/khtml_part.cpp:
        (KHTMLPart::requestObject):
        (KHTMLPart::selectFrameElementInParentIfFullySelected):
        (KHTMLPart::handleFallbackContent):
        * khtml/khtml_part.h:
        * khtml/khtmlpart_p.h:
        (khtml::ChildFrame::ChildFrame):
        * khtml/rendering/render_frames.cpp:
        (RenderPartObject::RenderPartObject):
        (RenderPartObject::updateWidget):
        * khtml/rendering/render_frames.h:
        (khtml::RenderPart::hasFallbackContent):
        * khtml/rendering/render_replaced.cpp:
        (RenderReplaced::RenderReplaced):
        * kwq/KWQKHTMLPart.mm:
        (KWQKHTMLPart::createPart):
        * kwq/WebCoreBridge.h:
        * kwq/WebCoreBridge.mm:
        (-[WebCoreBridge mainResourceError]):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@9095 268f45cc-cd09-0410-ab3c-d52691b4dbfc

13 files changed:
WebCore/ChangeLog-2005-08-23
WebCore/khtml/css/html4.css
WebCore/khtml/html/html_objectimpl.cpp
WebCore/khtml/html/html_objectimpl.h
WebCore/khtml/khtml_part.cpp
WebCore/khtml/khtml_part.h
WebCore/khtml/khtmlpart_p.h
WebCore/khtml/rendering/render_frames.cpp
WebCore/khtml/rendering/render_frames.h
WebCore/khtml/rendering/render_replaced.cpp
WebCore/kwq/KWQKHTMLPart.mm
WebCore/kwq/WebCoreBridge.h
WebCore/kwq/WebCoreBridge.mm

index 4dfd86e42f155f16c1efd128e44969b6a25d9144..a610b073044d2bb9429aaffeea132e57cc38b8c9 100644 (file)
@@ -1,3 +1,43 @@
+2005-05-03  David Hyatt  <hyatt@apple.com>
+
+       Fix for object element to support fallback content.  WIth this change Safari passes the Acid2 test.
+       
+        Reviewed by Maciej
+
+        * khtml/css/html4.css:
+        * khtml/html/html_objectimpl.cpp:
+        (HTMLObjectElementImpl::HTMLObjectElementImpl):
+        (HTMLObjectElementImpl::parseHTMLAttribute):
+        (HTMLObjectElementImpl::rendererIsNeeded):
+        (HTMLObjectElementImpl::createRenderer):
+        (HTMLObjectElementImpl::attach):
+        (HTMLObjectElementImpl::detach):
+        (HTMLObjectElementImpl::recalcStyle):
+        (HTMLObjectElementImpl::childrenChanged):
+        (HTMLObjectElementImpl::isURLAttribute):
+        (HTMLObjectElementImpl::isImageType):
+        (HTMLObjectElementImpl::renderFallbackContent):
+        * khtml/html/html_objectimpl.h:
+        * khtml/khtml_part.cpp:
+        (KHTMLPart::requestObject):
+        (KHTMLPart::selectFrameElementInParentIfFullySelected):
+        (KHTMLPart::handleFallbackContent):
+        * khtml/khtml_part.h:
+        * khtml/khtmlpart_p.h:
+        (khtml::ChildFrame::ChildFrame):
+        * khtml/rendering/render_frames.cpp:
+        (RenderPartObject::RenderPartObject):
+        (RenderPartObject::updateWidget):
+        * khtml/rendering/render_frames.h:
+        (khtml::RenderPart::hasFallbackContent):
+        * khtml/rendering/render_replaced.cpp:
+        (RenderReplaced::RenderReplaced):
+        * kwq/KWQKHTMLPart.mm:
+        (KWQKHTMLPart::createPart):
+        * kwq/WebCoreBridge.h:
+        * kwq/WebCoreBridge.mm:
+        (-[WebCoreBridge mainResourceError]):
+
 2005-05-01  Darin Adler  <darin@apple.com>
 
         - move to Xcode native targets and stop checking in generated files
index e6fe850af788047d39214a73d0debef0296f6021..d692c67ac05330b1d5d78695e12a1d65f401a329 100644 (file)
@@ -87,11 +87,6 @@ q:after {
     /* FIXME: content: close-quote; */
 }
 
-iframe, embed, object {
-    width: 300px;
-    height: 150px
-}
-
 center {
     display: block;
     /* special centering to be able to emulate the html4/netscape behaviour */
index 2d7c4ba587c10d0fd90c6d5b4ef923af8e2e8253..ee5c392736f953f0cc7b3bd15e4a7379ed07d82a 100644 (file)
@@ -388,6 +388,7 @@ HTMLObjectElementImpl::HTMLObjectElementImpl(DocumentPtr *doc)
 #endif
 {
     needWidgetUpdate = false;
+    m_useFallbackContent = false;
 }
 
 HTMLObjectElementImpl::~HTMLObjectElementImpl()
@@ -458,7 +459,7 @@ void HTMLObjectElementImpl::parseHTMLAttribute(HTMLAttributeImpl *attr)
           serviceType = serviceType.left( pos );
       if (m_render)
           needWidgetUpdate = true;
-      if (!canRenderImageType(serviceType) && m_imageLoader) {
+      if (!isImageType() && m_imageLoader) {
           delete m_imageLoader;
           m_imageLoader = 0;
       }
@@ -467,7 +468,7 @@ void HTMLObjectElementImpl::parseHTMLAttribute(HTMLAttributeImpl *attr)
       url = khtml::parseURL(  val ).string();
       if (m_render)
           needWidgetUpdate = true;
-      if (m_render && canRenderImageType(serviceType)) {
+      if (m_render && isImageType()) {
           if (!m_imageLoader)
               m_imageLoader = new HTMLImageLoader(this);
           m_imageLoader->updateFromElement();
@@ -505,9 +506,8 @@ DocumentImpl* HTMLObjectElementImpl::contentDocument() const
 
 bool HTMLObjectElementImpl::rendererIsNeeded(RenderStyle *style)
 {
-    if (canRenderImageType(serviceType)) {
+    if (m_useFallbackContent || isImageType())
         return HTMLElementImpl::rendererIsNeeded(style);
-    }
 
     KHTMLPart* part = getDocument()->part();
     if (!part || !part->pluginsEnabled()) {
@@ -528,9 +528,10 @@ bool HTMLObjectElementImpl::rendererIsNeeded(RenderStyle *style)
 
 RenderObject *HTMLObjectElementImpl::createRenderer(RenderArena *arena, RenderStyle *style)
 {
-    if (canRenderImageType(serviceType)) {
+    if (m_useFallbackContent)
+        return RenderObject::createObject(this, style);
+    if (isImageType())
         return new (arena) RenderImage(this);
-    }
     return new (arena) RenderPartObject(this);
 }
 
@@ -538,8 +539,8 @@ void HTMLObjectElementImpl::attach()
 {
     HTMLElementImpl::attach();
 
-    if (m_render) {
-        if (canRenderImageType(serviceType)) {
+    if (m_render && !m_useFallbackContent) {
+        if (isImageType()) {
             if (!m_imageLoader)
                 m_imageLoader = new HTMLImageLoader(this);
             m_imageLoader->updateFromElement();
@@ -565,7 +566,7 @@ void HTMLObjectElementImpl::attach()
 void HTMLObjectElementImpl::detach()
 {
     // Only bother with an unload event if we had a render object.  - dwh
-    if (attached() && m_render)
+    if (attached() && m_render && !m_useFallbackContent)
         // ### do this when we are actualy removed from document instead
         dispatchHTMLEvent(EventImpl::UNLOAD_EVENT,false,false);
 
@@ -574,7 +575,7 @@ void HTMLObjectElementImpl::detach()
 
 void HTMLObjectElementImpl::recalcStyle(StyleChange ch)
 {
-    if (needWidgetUpdate && m_render && !canRenderImageType(serviceType)) {
+    if (!m_useFallbackContent && needWidgetUpdate && m_render && !isImageType()) {
         // Set needWidgetUpdate to false before calling updateWidget because updateWidget may cause
         // this method or attach (which also calls updateWidget) to be called.
         needWidgetUpdate = false;
@@ -586,7 +587,7 @@ void HTMLObjectElementImpl::recalcStyle(StyleChange ch)
 
 void HTMLObjectElementImpl::childrenChanged()
 {
-    if (inDocument()) {
+    if (inDocument() && !m_useFallbackContent) {
         needWidgetUpdate = true;
         setChanged();
     }
@@ -597,6 +598,39 @@ bool HTMLObjectElementImpl::isURLAttribute(AttributeImpl *attr) const
     return (attr->id() == ATTR_DATA || (attr->id() == ATTR_USEMAP && attr->value().domString()[0] != '#'));
 }
 
+bool HTMLObjectElementImpl::isImageType()
+{
+    if (serviceType.isEmpty() && url.startsWith("data:")) {
+        // Extract the MIME type from the data URL.
+        int index = url.find(';');
+        if (index == -1)
+            index = url.find(',');
+        if (index != -1) {
+            int len = index - 5;
+            if (len > 0)
+                serviceType = url.mid(5, len);
+            else
+                serviceType = "text/plain"; // Data URLs with no MIME type are considered text/plain.
+        }
+    }
+
+    return canRenderImageType(serviceType);
+}
+
+void HTMLObjectElementImpl::renderFallbackContent()
+{
+    if (m_useFallbackContent)
+        return;
+
+    // Mark ourselves as using the fallback content.
+    m_useFallbackContent = true;
+
+    // Now do a detach and reattach.    
+    // FIXME: Style gets recalculated which is suboptimal.
+    detach();
+    attach();
+}
+
 // -------------------------------------------------------------------------
 
 HTMLParamElementImpl::HTMLParamElementImpl(DocumentPtr *doc)
index 7afdbb3fd078790147152fd3d965f9913d8b54bb..fe6297648f04b147e7788e820bebaa5777846caa 100644 (file)
@@ -139,6 +139,10 @@ public:
     
     virtual bool isURLAttribute(AttributeImpl *attr) const;
 
+    bool isImageType();
+
+    void renderFallbackContent();
+
 #if APPLE_CHANGES
     KJS::Bindings::Instance *getObjectInstance() const;
 #endif
@@ -146,7 +150,8 @@ public:
     QString serviceType;
     QString url;
     QString classId;
-    bool needWidgetUpdate;
+    bool needWidgetUpdate : 1;
+    bool m_useFallbackContent : 1;
     HTMLImageLoader* m_imageLoader;
 
 #if APPLE_CHANGES
index 178802c993aad1073de90b805021b4f07a7aab8d..c7355d69e8d646e4da842cc5e440d7f3745d9859 100644 (file)
@@ -52,6 +52,7 @@
 #include "html/html_baseimpl.h"
 #include "html/html_miscimpl.h"
 #include "html/html_imageimpl.h"
+#include "html/html_objectimpl.h"
 #include "rendering/render_block.h"
 #include "rendering/render_text.h"
 #include "rendering/render_frames.h"
@@ -3143,6 +3144,7 @@ bool KHTMLPart::requestObject( khtml::RenderPart *frame, const QString &url, con
   (*it).m_type = khtml::ChildFrame::Object;
   (*it).m_paramNames = paramNames;
   (*it).m_paramValues = paramValues;
+  (*it).m_hasFallbackContent = frame->hasFallbackContent();
 
   KURL completedURL;
   if (!url.isEmpty())
@@ -5885,5 +5887,20 @@ void KHTMLPart::selectFrameElementInParentIfFullySelected()
     parent->setSelection(Selection(beforeOwnerElement, afterOwnerElement));
 }
 
+void KHTMLPart::handleFallbackContent()
+{
+    KHTMLPart *parent = parentPart();
+    if (!parent)
+        return;
+    ChildFrame *childFrame = parent->childFrame(this);
+    if (!childFrame || childFrame->m_type != ChildFrame::Object)
+        return;
+    khtml::RenderPart *renderPart = childFrame->m_frame;
+    if (!renderPart)
+        return;
+    HTMLObjectElementImpl* elt = static_cast<HTMLObjectElementImpl *>(renderPart->element());
+    elt->renderFallbackContent();
+}
+
 using namespace KParts;
 #include "khtml_part.moc"
index 963860abaa27f2487c7d97b5a1c708defb6f00d2..a422707746880d1158587f614b925317d3bb8cf2 100644 (file)
@@ -1295,6 +1295,8 @@ public:
   // Call this after doing user-triggered selections to make it easy to delete the frame you entirely selected.
   void selectFrameElementInParentIfFullySelected();
   
+  void handleFallbackContent();
+
 private:
   khtml::ChildFrame *childFrame( const QObject *obj );
 
index 55e53eb45d2f7999c750e8ecd1a6d3965a3a5d5e..835ff15f804408d32cafb6c324abeb2dd812e016 100644 (file)
@@ -61,7 +61,7 @@ namespace khtml
   {
       enum Type { Frame, IFrame, Object };
 
-      ChildFrame() { m_bCompleted = false; m_bPreloaded = false; m_type = Frame; m_bNotify = false; }
+      ChildFrame() { m_bCompleted = false; m_bPreloaded = false; m_type = Frame; m_bNotify = false; m_hasFallbackContent = false; }
 
 #if !APPLE_CHANGES
       ~ChildFrame() { if (m_run) m_run->abort(); }
@@ -85,6 +85,7 @@ namespace khtml
     QStringList m_paramNames;
     QStringList m_paramValues;
     bool m_bNotify;
+    bool m_hasFallbackContent;
   };
 }
 
index dc042b7cfbb02a2044669e780c396dc65529a367..b7baae099031e8e736184233f17b2acb4bf06da3 100644 (file)
@@ -612,26 +612,6 @@ bool RenderPart::partLoadingErrorNotify(khtml::ChildFrame *, const KURL& , const
     return false;
 }
 
-int RenderPart::intrinsicWidth() const
-{
-  // KDE may need a non-zero width here, although this will mess up pages (e.g., thinker.org).
-#if APPLE_CHANGES
-    return 0;
-#else
-    return 300;
-#endif
-}
-
-int RenderPart::intrinsicHeight() const
-{
-  // KDE may need a non-zero height here, although this will mess up pages (e.g., thinker.org).
-#if APPLE_CHANGES
-    return 0;
-#else
-    return 200;
-#endif
-}
-
 void RenderPart::slotViewCleared()
 {
 }
@@ -681,6 +661,7 @@ RenderPartObject::RenderPartObject( DOM::HTMLElementImpl* element )
 {
     // init RenderObject attributes
     setInline(true);
+    m_hasFallbackContent = false;
 }
 
 void RenderPartObject::updateWidget()
@@ -831,7 +812,16 @@ void RenderPartObject::updateWidget()
       params.append( QString::fromLatin1("__KHTML__CODEBASE=\"%1\"").arg( o->getAttribute(ATTR_CODEBASE).string() ) );
 #endif
 
-      part->requestObject( this, url, serviceType, paramNames, paramValues );
+      // Find out if we support fallback content.
+      m_hasFallbackContent = false;
+      for (NodeImpl *child = o->firstChild(); child && !m_hasFallbackContent; child = child->nextSibling()) {
+          if ((!child->isTextNode() && child->id() != ID_EMBED && child->id() != ID_PARAM) || // Discount <embed> and <param>
+              (child->isTextNode() && !child->containsOnlyWhitespace()))
+              m_hasFallbackContent = true;
+      }
+      bool success = part->requestObject( this, url, serviceType, paramNames, paramValues );
+      if (!success && m_hasFallbackContent)
+          o->renderFallbackContent();
   } else if ( element()->id() == ID_EMBED ) {
 
       HTMLEmbedElementImpl *o = static_cast<HTMLEmbedElementImpl *>(element());
index ad6940151f5c286e50e0a9e0ec332a9ae9908abd..c080046455a7852bf45709458d25944428c86bf4 100644 (file)
@@ -119,11 +119,13 @@ public:
      */
     virtual bool partLoadingErrorNotify( khtml::ChildFrame *childFrame, const KURL& url, const QString& serviceType );
 
-    virtual int intrinsicWidth() const;
-    virtual int intrinsicHeight() const;
+    bool hasFallbackContent() const { return m_hasFallbackContent; }
 
 public slots:
     virtual void slotViewCleared();
+
+protected:
+    bool m_hasFallbackContent;
 };
 
 class RenderFrame : public RenderPart
index c7c7723f1a3ccedb01c3bffa011e3ac80fba6ccd..35b73401f23b2731ac112491921d272249406e10 100644 (file)
@@ -51,7 +51,7 @@ RenderReplaced::RenderReplaced(DOM::NodeImpl* node)
     // init RenderObject attributes
     setReplaced(true);
 
-    m_intrinsicWidth = 200;
+    m_intrinsicWidth = 300;
     m_intrinsicHeight = 150;
     m_selectionState = SelectionNone;
 }
index 206807dc4bbe983aa9f5bdde56de451b073f501d..30b8a02413c64017bcb60fd675e37ba235c84090 100644 (file)
@@ -798,8 +798,17 @@ ReadOnlyPart *KWQKHTMLPart::createPart(const ChildFrame &child, const KURL &url,
     KWQ_BLOCK_EXCEPTIONS;
     ReadOnlyPart *part;
 
-    BOOL needFrame = [_bridge frameRequiredForMIMEType:mimeType.getNSString() URL:url.getNSURL()];
-    if (child.m_type == ChildFrame::Object && !needFrame) {
+    ObjectElementType objectType = ObjectElementFrame;
+    if (child.m_type == ChildFrame::Object)
+        objectType = [_bridge determineObjectFromMIMEType:mimeType.getNSString() URL:url.getNSURL()];
+    
+    if (objectType == ObjectElementNone) {
+        if (child.m_hasFallbackContent)
+            return NULL;
+        objectType = ObjectElementPlugin; // Since no fallback content exists, we'll make a plugin and show the error dialog.
+    }
+
+    if (objectType == ObjectElementPlugin) {
         KWQPluginPart *newPart = new KWQPluginPart;
         newPart->setWidget(new QWidget([_bridge viewForPluginWithURL:url.getNSURL()
                                                       attributeNames:child.m_paramNames.getNSArray()
@@ -827,9 +836,8 @@ ReadOnlyPart *KWQKHTMLPart::createPart(const ChildFrame &child, const KURL &url,
        // This call needs to return an object with a ref, since the caller will expect to own it.
        // childBridge owns the only ref so far.
         part = [childBridge part];
-        if (part) {
+        if (part)
             part->ref();
-        }
     }
 
     return part;
index bc0f465cab18127cd785d2997b0a5e08f58f44ac..2a1fc12be247721e0fa386ff21c4ae4f3dd0fb76 100644 (file)
@@ -164,6 +164,14 @@ typedef enum {
     WebUndoActionTyping,
 } WebUndoAction;
 
+typedef enum
+{
+    ObjectElementNone,
+    ObjectElementImage,
+    ObjectElementFrame,
+    ObjectElementPlugin,
+} ObjectElementType;
+
 // WebCoreBridge objects are used by WebCore to abstract away operations that need
 // to be implemented by library clients, for example WebKit. The objects are also
 // used in the opposite direction, for simple access to WebCore functions without dealing
@@ -217,6 +225,8 @@ typedef enum {
 - (void)end;
 - (void)stop;
 
+- (void)mainResourceError;
+
 - (NSURL *)URL;
 - (NSURL *)baseURL;
 - (NSString *)referrer;
@@ -547,7 +557,7 @@ typedef enum {
 
 - (int)getObjectCacheSize;
 
-- (BOOL)frameRequiredForMIMEType:(NSString*)MIMEType URL:(NSURL *)URL;
+- (ObjectElementType)determineObjectFromMIMEType:(NSString*)MIMEType URL:(NSURL*)URL;
 
 - (void)loadEmptyDocumentSynchronously;
 
index 4866ffb1cb4b4fff80ad54d12af355150ad00da2..81757b7f2a2740f516b5dbc5a739b46e5c14cb0f 100644 (file)
@@ -501,6 +501,11 @@ static bool initializedKJS = FALSE;
     _part->stop();
 }
 
+- (void)mainResourceError
+{
+    _part->handleFallbackContent();
+}
+
 - (void)createKHTMLViewWithNSView:(NSView *)view marginWidth:(int)mw marginHeight:(int)mh
 {
     // If we own the view, delete the old one - otherwise the render _part will take care of deleting the view.