webengine/osswebengine/WebCore/rendering/RenderPartObject.cpp
changeset 0 dd21522fd290
child 67 4917f9bf7995
child 68 92a765b5b3e7
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     1 /**
       
     2  * This file is part of the KDE project.
       
     3  *
       
     4  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
       
     5  *           (C) 2000 Simon Hausmann <hausmann@kde.org>
       
     6  *           (C) 2000 Stefan Schimanski (1Stein@gmx.de)
       
     7  * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
       
     8  *
       
     9  * This library is free software; you can redistribute it and/or
       
    10  * modify it under the terms of the GNU Library General Public
       
    11  * License as published by the Free Software Foundation; either
       
    12  * version 2 of the License, or (at your option) any later version.
       
    13  *
       
    14  * This library is distributed in the hope that it will be useful,
       
    15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    17  * Library General Public License for more details.
       
    18  *
       
    19  * You should have received a copy of the GNU Library General Public License
       
    20  * along with this library; see the file COPYING.LIB.  If not, write to
       
    21  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
       
    22  * Boston, MA 02110-1301, USA.
       
    23  *
       
    24  */
       
    25 #include "config.h"
       
    26 #include "RenderPartObject.h"
       
    27 
       
    28 #include "Document.h"
       
    29 #include "EventHandler.h"
       
    30 #include "Frame.h"
       
    31 #include "FrameLoader.h"
       
    32 #include "FrameLoaderClient.h"
       
    33 #include "FrameTree.h"
       
    34 #include "FrameView.h"
       
    35 #include "HTMLEmbedElement.h"
       
    36 #if PLATFORM(SYMBIAN)  
       
    37 #include "HTMLBgsoundElement.h"
       
    38 #include "WebCoreWidget.h"
       
    39 #endif
       
    40 #include "HTMLIFrameElement.h"
       
    41 #include "HTMLNames.h"
       
    42 #include "HTMLObjectElement.h"
       
    43 #include "HTMLParamElement.h"
       
    44 #include "KURL.h"
       
    45 #include "MIMETypeRegistry.h"
       
    46 #include "Page.h"
       
    47 #include "RenderView.h"
       
    48 #include "Text.h"
       
    49 #include "Settings.h"
       
    50 
       
    51 namespace WebCore {
       
    52 
       
    53 using namespace HTMLNames;
       
    54 
       
    55 RenderPartObject::RenderPartObject(HTMLFrameOwnerElement* element)
       
    56     : RenderPart(element)
       
    57 {
       
    58     // init RenderObject attributes
       
    59     setInline(true);
       
    60     m_hasFallbackContent = false;
       
    61 }
       
    62 
       
    63 RenderPartObject::~RenderPartObject()
       
    64 {
       
    65     if (m_view)
       
    66         m_view->removeWidgetToUpdate(this);
       
    67 }
       
    68 
       
    69 static bool isURLAllowed(Document *doc, const String &url)
       
    70 {
       
    71     KURL newURL(doc->completeURL(url.deprecatedString()));
       
    72     newURL.setRef(DeprecatedString::null);
       
    73     
       
    74     if (doc->frame()->page()->frameCount() >= 200)
       
    75         return false;
       
    76 
       
    77     // We allow one level of self-reference because some sites depend on that.
       
    78     // But we don't allow more than one.
       
    79     bool foundSelfReference = false;
       
    80     for (Frame *frame = doc->frame(); frame; frame = frame->tree()->parent()) {
       
    81         KURL frameURL = frame->loader()->url();
       
    82         frameURL.setRef(DeprecatedString::null);
       
    83         if (frameURL == newURL) {
       
    84             if (foundSelfReference)
       
    85                 return false;
       
    86             foundSelfReference = true;
       
    87         }
       
    88     }
       
    89     return true;
       
    90 }
       
    91 
       
    92 static inline void mapClassIdToServiceType(const String& classId, String& serviceType)
       
    93 {
       
    94     // It is ActiveX, but the nsplugin system handling
       
    95     // should also work, that's why we don't override the
       
    96     // serviceType with application/x-activex-handler
       
    97     // but let the KTrader in khtmlpart::createPart() detect
       
    98     // the user's preference: launch with activex viewer or
       
    99     // with nspluginviewer (Niko)
       
   100     if (classId.contains("D27CDB6E-AE6D-11cf-96B8-444553540000"))
       
   101         serviceType = "application/x-shockwave-flash";
       
   102     else if (classId.contains("CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA"))
       
   103         serviceType = "audio/x-pn-realaudio-plugin";
       
   104     else if (classId.contains("02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"))
       
   105         serviceType = "video/quicktime";
       
   106     else if (classId.contains("166B1BCA-3F9C-11CF-8075-444553540000"))
       
   107         serviceType = "application/x-director";
       
   108     else if (classId.contains("6BF52A52-394A-11d3-B153-00C04F79FAA6"))
       
   109         serviceType = "application/x-mplayer2";
       
   110     else if (!classId.isEmpty())
       
   111         // We have a clsid, means this is activex (Niko)
       
   112         serviceType = "application/x-activex-handler";
       
   113     // TODO: add more plugins here
       
   114 }
       
   115 
       
   116 void RenderPartObject::updateWidget(bool onlyCreateNonNetscapePlugins)
       
   117 {
       
   118   String url;
       
   119   String serviceType;
       
   120   Vector<String> paramNames;
       
   121   Vector<String> paramValues;
       
   122   Frame* frame = m_view->frame();
       
   123   
       
   124   if (element()->hasTagName(objectTag)) {
       
   125 
       
   126       HTMLObjectElement* o = static_cast<HTMLObjectElement*>(element());
       
   127 
       
   128       if (!o->isComplete())
       
   129         return;
       
   130       // Check for a child EMBED tag.
       
   131       HTMLEmbedElement* embed = 0;
       
   132       for (Node* child = o->firstChild(); child;) {
       
   133           if (child->hasTagName(embedTag)) {
       
   134               embed = static_cast<HTMLEmbedElement*>(child);
       
   135               break;
       
   136           } else if (child->hasTagName(objectTag))
       
   137               child = child->nextSibling();         // Don't descend into nested OBJECT tags
       
   138           else
       
   139               child = child->traverseNextNode(o);   // Otherwise descend (EMBEDs may be inside COMMENT tags)
       
   140       }
       
   141       
       
   142       // Use the attributes from the EMBED tag instead of the OBJECT tag including WIDTH and HEIGHT.
       
   143       HTMLElement *embedOrObject;
       
   144       if (embed) {
       
   145           embedOrObject = (HTMLElement *)embed;
       
   146           url = embed->url;
       
   147           serviceType = embed->m_serviceType;
       
   148       } else
       
   149           embedOrObject = (HTMLElement *)o;
       
   150       
       
   151       // If there was no URL or type defined in EMBED, try the OBJECT tag.
       
   152       if (url.isEmpty())
       
   153           url = o->m_url;
       
   154       if (serviceType.isEmpty())
       
   155           serviceType = o->m_serviceType;
       
   156       
       
   157       HashSet<StringImpl*, CaseInsensitiveHash<StringImpl*> > uniqueParamNames;
       
   158       
       
   159       // Scan the PARAM children.
       
   160       // Get the URL and type from the params if we don't already have them.
       
   161       // Get the attributes from the params if there is no EMBED tag.
       
   162       Node *child = o->firstChild();
       
   163       while (child && (url.isEmpty() || serviceType.isEmpty() || !embed)) {
       
   164           if (child->hasTagName(paramTag)) {
       
   165               HTMLParamElement* p = static_cast<HTMLParamElement*>(child);
       
   166               String name = p->name().lower();
       
   167               if (url.isEmpty() && (name == "src" || name == "movie" || name == "code" || name == "url"))
       
   168                   url = p->value();
       
   169               if (serviceType.isEmpty() && name == "type") {
       
   170                   serviceType = p->value();
       
   171                   int pos = serviceType.find(";");
       
   172                   if (pos != -1)
       
   173                       serviceType = serviceType.left(pos);
       
   174               }
       
   175               if (!embed && !name.isEmpty()) {
       
   176                   uniqueParamNames.add(p->name().impl());
       
   177                   paramNames.append(p->name());
       
   178                   paramValues.append(p->value());
       
   179               }
       
   180           }
       
   181           child = child->nextSibling();
       
   182       }
       
   183       
       
   184       // When OBJECT is used for an applet via Sun's Java plugin, the CODEBASE attribute in the tag
       
   185       // points to the Java plugin itself (an ActiveX component) while the actual applet CODEBASE is
       
   186       // in a PARAM tag. See <http://java.sun.com/products/plugin/1.2/docs/tags.html>. This means
       
   187       // we have to explicitly suppress the tag's CODEBASE attribute if there is none in a PARAM,
       
   188       // else our Java plugin will misinterpret it. [4004531]
       
   189       String codebase;
       
   190       if (!embed && MIMETypeRegistry::isJavaAppletMIMEType(serviceType)) {
       
   191           codebase = "codebase";
       
   192           uniqueParamNames.add(codebase.impl()); // pretend we found it in a PARAM already
       
   193       }
       
   194       
       
   195       // Turn the attributes of either the EMBED tag or OBJECT tag into arrays, but don't override PARAM values.
       
   196       NamedAttrMap* attributes = embedOrObject->attributes();
       
   197       if (attributes) {
       
   198           for (unsigned i = 0; i < attributes->length(); ++i) {
       
   199               Attribute* it = attributes->attributeItem(i);
       
   200               const AtomicString& name = it->name().localName();
       
   201               if (embed || !uniqueParamNames.contains(name.impl())) {
       
   202                   paramNames.append(name.domString());
       
   203                   paramValues.append(it->value().domString());
       
   204               }
       
   205           }
       
   206       }
       
   207       
       
   208       // If we still don't have a type, try to map from a specific CLASSID to a type.
       
   209       if (serviceType.isEmpty() && !o->m_classId.isEmpty())
       
   210           mapClassIdToServiceType(o->m_classId, serviceType);
       
   211       
       
   212       // If no URL and type, abort.
       
   213       if (url.isEmpty() && serviceType.isEmpty())
       
   214           return;
       
   215       if (!isURLAllowed(document(), url))
       
   216           return;
       
   217 
       
   218       // Find out if we support fallback content.
       
   219       m_hasFallbackContent = false;
       
   220       for (Node *child = o->firstChild(); child && !m_hasFallbackContent; child = child->nextSibling()) {
       
   221            if ((!child->isTextNode() && !child->hasTagName(embedTag) && !child->hasTagName(paramTag)) || // Discount <embed> and <param>
       
   222                (child->isTextNode() && !static_cast<Text*>(child)->containsOnlyWhitespace()))
       
   223               m_hasFallbackContent = true;
       
   224       }
       
   225       
       
   226       if (onlyCreateNonNetscapePlugins) {
       
   227           KURL completedURL;
       
   228           if (!url.isEmpty())
       
   229               completedURL = frame->loader()->completeURL(url);
       
   230         
       
   231           if (frame->loader()->client()->objectContentType(completedURL, serviceType) == ObjectContentNetscapePlugin)
       
   232               return;
       
   233       }
       
   234       
       
   235       bool success = frame->loader()->requestObject(this, url, AtomicString(o->name()), serviceType, paramNames, paramValues);
       
   236       if (!success && m_hasFallbackContent)
       
   237           o->renderFallbackContent();
       
   238   } else if (element()->hasTagName(embedTag)) {
       
   239       HTMLEmbedElement *o = static_cast<HTMLEmbedElement*>(element());
       
   240       url = o->url;
       
   241       serviceType = o->m_serviceType;
       
   242 
       
   243       if (url.isEmpty() && serviceType.isEmpty())
       
   244           return;
       
   245       if (!isURLAllowed(document(), url))
       
   246           return;
       
   247       
       
   248       // add all attributes set on the embed object
       
   249       NamedAttrMap* a = o->attributes();
       
   250       if (a) {
       
   251           for (unsigned i = 0; i < a->length(); ++i) {
       
   252               Attribute* it = a->attributeItem(i);
       
   253               paramNames.append(it->name().localName().domString());
       
   254               paramValues.append(it->value().domString());
       
   255           }
       
   256       }
       
   257       
       
   258       if (onlyCreateNonNetscapePlugins) {
       
   259           KURL completedURL;
       
   260           if (!url.isEmpty())
       
   261               completedURL = frame->loader()->completeURL(url);
       
   262           
       
   263           if (frame->loader()->client()->objectContentType(completedURL, serviceType) == ObjectContentNetscapePlugin)
       
   264               return;
       
   265           
       
   266       }
       
   267       
       
   268       frame->loader()->requestObject(this, url, o->getAttribute(nameAttr), serviceType, paramNames, paramValues);
       
   269   }
       
   270 #if PLATFORM(SYMBIAN)  
       
   271     else if (element()->hasTagName(bgsoundTag)) {      
       
   272     
       
   273         HTMLBgsoundElement *o = static_cast<HTMLBgsoundElement*>(element());
       
   274         url = o->url;
       
   275         serviceType = o->serviceType;
       
   276 
       
   277         if (url.isEmpty() && serviceType.isEmpty())
       
   278             return;
       
   279     
       
   280         if (!isURLAllowed(document(), url))
       
   281             return;
       
   282 
       
   283         // add all attributes set on the embed object
       
   284         NamedAttrMap* a = o->attributes();
       
   285         if (a) {
       
   286             bool lpattrfound = false;
       
   287 
       
   288             for (unsigned i = 0; i < a->length(); ++i) {
       
   289                 Attribute* it = a->attributeItem(i);
       
   290                 paramNames.append(it->name().localName().domString());              
       
   291 
       
   292                 if (it->name() == loopAttr) {                
       
   293 
       
   294                     lpattrfound = true;                              
       
   295 
       
   296                     if (it->value().toInt()>0 && it->value().toInt()<=50){
       
   297                         paramValues.append(it->value().domString());      
       
   298                     } else {
       
   299                         paramValues.append("50");                          
       
   300                     }                            
       
   301 
       
   302                 } else {
       
   303                     paramValues.append(it->value().domString());  
       
   304                 }                                                                
       
   305             }
       
   306 
       
   307             if (!lpattrfound) {
       
   308                 paramNames.append("loop");              
       
   309                 paramValues.append("50");  
       
   310             }          
       
   311         }
       
   312         
       
   313          frame->loader()->requestObject(this, url, o->getAttribute(nameAttr), serviceType, paramNames, paramValues);    
       
   314     }
       
   315 #endif
       
   316 }
       
   317 
       
   318 void RenderPartObject::layout()
       
   319 {
       
   320     ASSERT(needsLayout());
       
   321 
       
   322     FrameView* childFrameView = static_cast<FrameView*>(m_widget);
       
   323     RenderView* childRoot = 0;
       
   324     calcWidth();
       
   325     calcHeight();
       
   326     adjustOverflowForBoxShadow();
       
   327 
       
   328     RenderPart::layout();
       
   329 
       
   330     if (!m_widget && m_view)
       
   331         m_view->addWidgetToUpdate(this);
       
   332     
       
   333     setNeedsLayout(false);
       
   334 }
       
   335 
       
   336 void RenderPartObject::viewCleared()
       
   337 {
       
   338     if (element() && m_widget && m_widget->isFrameView()) {
       
   339         FrameView* view = static_cast<FrameView*>(m_widget);
       
   340         int marginw = -1;
       
   341         int marginh = -1;
       
   342         if (element()->hasTagName(iframeTag)) {
       
   343             HTMLIFrameElement* frame = static_cast<HTMLIFrameElement*>(element());
       
   344             marginw = frame->getMarginWidth();
       
   345             marginh = frame->getMarginHeight();
       
   346         }
       
   347         if (marginw != -1)
       
   348             view->setMarginWidth(marginw);
       
   349         if (marginh != -1)
       
   350             view->setMarginHeight(marginh);
       
   351     }
       
   352 }
       
   353 
       
   354 #if PLATFORM(SYMBIAN)
       
   355 bool RenderPartObject::isFocusable() const
       
   356 {
       
   357     if (m_widget)
       
   358         return m_widget->isFocusable();
       
   359     return false;
       
   360 }
       
   361 
       
   362 int RenderPartObject::calcReplacedWidth() const
       
   363 {
       
   364     if (m_widget && (m_widget->getView())->hasResized())  {        
       
   365         IntRect newRect = m_widget->frameGeometry();
       
   366         int newWidth = newRect.width();
       
   367         if (newWidth > 0) {
       
   368             return newWidth;
       
   369         }
       
   370     }
       
   371     return RenderReplaced::calcReplacedWidth();
       
   372 }
       
   373 
       
   374 int RenderPartObject::calcReplacedHeight() const
       
   375 {
       
   376     if (m_widget && (m_widget->getView())->hasResized())  {        
       
   377         IntRect newRect = m_widget->frameGeometry();
       
   378         int newHeight = newRect.height();
       
   379         if (newHeight > 0) {
       
   380             return newHeight;
       
   381         }       
       
   382     }
       
   383      
       
   384     return RenderReplaced::calcReplacedHeight();
       
   385 }
       
   386 
       
   387 
       
   388 #endif
       
   389 
       
   390 }